Table of Contents

What's new for DevOps in Neos 3.2

This article gathers the Neos 3.2 changes that matter to an already-deployed environment: infrastructure and hosting, runtime configuration, operations and monitoring, and migration or upgrade steps. It is a curated digest for ops/infra teams operating a Neos cluster in production — it complements, and links out to, the 3.2 key insights and the full changelog rather than duplicating them.

Changes to framework development, cluster/metadata authoring, or authoring tooling are out of scope for this article.

Infrastructure and hosting

Recommended .NET SDK and Docker base images were updated twice during the 3.2 cycle, ending at .NET SDK 10.0.400 and runtime images 10.0.11. The final update also fixes ten published .NET CVEs (information disclosure, security-feature bypass, denial of service, elevation of privilege, and remote code execution). Rebuild and redeploy your business-cluster images against the updated base images to pick up these fixes. (17122, 18066, 18436)

A cluster can now be deployed on a shared host under a URL prefix. See Cluster prefix configuration. The gateway also now forwards the X-Forwarded-Prefix header to destination clusters for prefixed and nested routes, and the index of a nested cluster (e.g. /tenants/) is now served with a Cache-Control header in production — previously a browser could heuristically cache it, silently replaying a stale identity switch on re-navigation. (16745, 18208, 18061)

The gateway gained configurable CORS support (allowed origins, methods, headers, credentials, and preflight caching). See Gateway CORS configuration. (17868)

The dedicated SignalR service and its Kubernetes pod are gone. SignalR/WebSocket traffic now flows through backend services and the gateway, backed by the existing Redis backplane — one less component to operate. A namespace deployed with Neos 3.2 is only supported by Neos 3.2, 3.1 (patch 3.1.8+), or 3.0 (patch 3.0.20+) clusters. See SignalR with a Redis backplane. As part of the same simplification, NGINX-specific notification rewrites and prefix-redirect ingresses were removed, delegating that path handling to the gateway. (17688, 18490)

Several Helm chart changes affect upgrades and day-to-day operation:

  • Business-cluster frontend pods now accept configurable env and envFrom entries. (18154)
  • The chart now defaults to a Kubernetes RollingUpdate strategy (maxSurge: 1, maxUnavailable: 50%), with configurable per-service overrides. See Update strategy configuration. (17617)
  • Deployments now carry checksum annotations so a dependent configuration change triggers a rolling pod restart automatically. (18448)
  • authenticationSecret is now required in the Helm chart values, and an empty value is rejected — set it explicitly before upgrading if your values file relied on a default. (17599)
  • RabbitMQ moved from a Deployment to a StatefulSet, for stable pod identity and safer volume handling across upgrades. (17519)
  • The cert-manager annotation was fixed to properly enable certificate request and generation — useful for test environments without a Cloudflare proxy in front. (17871)

Reports can now be persisted to S3-compatible storage instead of only local/PVC storage. See S3 mode. (18140)

Date values in API context headers are now serialized as ISO 8601 strings before being sent between clusters, avoiding invalid forwarded headers that Cloudflare could reject and that would otherwise break downstream service invocations. (17342)

Runtime configuration

Background server methods now default to ASP.NET Core BackgroundService execution; Dapr Workflow execution is only used when explicitly configured. This is a breaking change for clusters that relied on the previous default — review your background server method configuration before upgrading. See Background service execution mode. (18533)

A LooseJsonDeserialization option (environment variable or appsettings) enables a more lenient JSON deserialization mode — allowing a string to be read into a numeric or bool property and vice versa — to quickly unblock a runtime deserialization failure introduced by the System.Text.Json migration (for example, a pub/sub payload where two clusters disagree on a property's type). Fixing the underlying type mismatch is still recommended, since the option degrades deserialization performance while enabled. See System.Text.Json breaking changes.

The Stimulsoft HTML5 report viewer's backend cache mode is now configurable, globally or per report, between the default ObjectCache and None. Disabling the cache is required when the reporting service runs with multiple replicas and reports allow viewer events (Save As, Print, etc.). (18202)

A cluster can declare a default ReportStyle for reports that don't name one themselves, via Reporting.DefaultReportStyleName. See Report styles. (18646)

Tenant Management now offers a structured editor for database server connection strings, with Main/Pooling/Security tabs and an Advanced tab retaining the raw provider string. See Database server connection strings. Plaintext connection string storage was also removed from Tenant Management — only encrypted connection strings are kept, and a migration-time validation blocks schema cleanup until existing connection strings have been encrypted. (17914, 17530)

The tenant selection screen can now be customized according to each tenant's status (disabled via Tenant Management, or currently unavailable, e.g. migrating). See Tenant selection endpoint configuration. (17602)

Operations and monitoring

Neos backend servers and task runners now expose normalized Prometheus metrics for their database connection pools (neos_db_pool_connections, neos_db_pool_max_connections). See Database connection pools and Database pool versus process scope. (18312)

A forced synchronous tenant caches rebuild (triggered by SetDatabaseClusterVersion) now waits for the store locks instead of failing immediately, so updating several clusters right after a deployment no longer returns "could not acquire lock" while a concurrent rebuild is still in progress. (17657)

The Report service gained bounded, detailed exception diagnostics, making report generation failures easier to investigate in production. (18370)

Automation-identity logs emitted during database migrations were reduced, cutting log noise on clusters that migrate frequently. (18320)

Migration and upgrade

If you use Neos RAG features with a PostgreSQL vector store, migrate from Kernel Memory to Vector Data. This requires adding new columns (document_id, chunk_index, chunk_count) to your existing vector tables. See Migration from Kernel Memory to Vector Data for the full migration steps. (17953)

Gateway routing for SignalR clients was fixed for mixed-version namespaces: a Neos 3.2 gateway now correctly routes SignalR clients still running 3.1 or 3.0. Relevant if you roll out 3.2 progressively across clusters of a namespace. (18618)

Database migrations for a cluster now run through background processing instead of blocking the request that triggered them — factor this into how you monitor a migration's completion. (17302)

Tenant Management adds first-class support for operating cluster migrations: a daily cleanup scheduled task (default 180-day retention, adjustable from Task Scheduler) removes old migration tracking data, and a dedicated migration tracking screen gives live progress updates with access to migration or simulation logs. A schema migration comparer fix also ensures check constraints are now tracked (previously dropped instead of preserved), and the migration simulation summary is handled correctly when a migration fails. (17899, 17646, 18263, 18317)

Three tenant management API methods are now isolated behind the gateway, restricted to the internal network: GetClusterVersions, GetTenantInfo, and GetTenantClusters. A related fix ensures forwarded-header handling properly isolates every InternalUseOnly server method behind the gateway. Review any external caller of these APIs before upgrading. (17434)

Additional security dependency updates fixed three published CVEs of HIGH severity (GHSA-f32c-w444-8ppv, GHSA-qj66-m88j-hmgj, GHSA-2v37-7h3g-55p8) — covered by the Kernel Memory to Vector Data migration above and general dependency updates. (17953, 18291, 18454)

PostgreSQL connections using localhost may time out after the Npgsql upgrade, depending on local network settings. See PostgreSQL localhost connection timeouts after the Npgsql upgrade for the available workarounds.

Minor changes

  • [Documentation] Clarified which Docker image versions to use for the frontend, backend, and task runner. See Business cluster images. (18168)
  • [Documentation] Added Redis persistence, troubleshooting, and backup and restore sections. (17281)
  • [Gateway] Fixed the api-documentation route not working for nested clusters. (18056)
  • Fixed a direct remote service invocation now returning 401 Unauthorized instead of 403 Forbidden when the request bypasses the gateway. (17608)
  • Fixed a misleading error message when the database connection fails at startup in single-tenant mode: it now correctly indicates a migration failure instead of an interceptor failure. (17594)
  • Fixed wrong tenant settings being used for sequences and the database exception converter in background server methods. (17872)
  • [Tenant Management] Fixed user synchronization during tenant creation and tenant migration state changes, preventing unintended cross-cluster sync events. (17408)
  • [Task Scheduler Client] Fixed scheduling tasks without arguments by sending a null arguments payload instead of failing. (18236)
  • Increased the minimum supported NPM version from 9 to 10 — relevant to any pipeline image used to build a cluster's frontend. (18121)
  • [Reporting] Reporting assets (templates and style bundles) are now retrieved through UTF-8 endpoints instead of Base64 ones (compatible with clusters based on Neos FMK 3.0 and later only). (18498)