v2.12.9
nats-io/nats-serverv2.12.9May 20, 2026by github-actions[bot]
AI Summary
A maintenance release for the 2.12 branch focusing on JetStream stability, performance optimizations, and dependency updates. It shares many JetStream fixes and improvements with the v2.14.1 release.
Key Highlights
- New monitoring metrics for tracking data to/from normal clients
- Improved JetStream performance metrics calculation and reduced lock contention
- Fixed various protocol errors, Raft stability issues, and memory leaks
- Updated Go version to 1.25.10
Full Release Notes
## Changelog Refer to the [2.12 Upgrade Guide](https://docs.nats.io/release-notes/whats_new/whats_new_212) for backwards compatibility notes with 2.11.x. ### Go Version - 1.25.10 (#8107) ### Dependencies - github.com/klauspost/compress v1.18.6 (#8124) - golang.org/x/crypto v0.51.0 (#8124) - golang.org/x/sys v0.44.0 (#8124) ### Added General - New metrics `in_client_msgs`, `in_client_bytes`, `out_client_msgs` and `out_client_bytes` are now available via the `/varz` monitoring endpoint for tracking data to/from normal clients only (#7851) ### Improved General - Client TLS certificates without subject DNs but with DNS subject alternate names are now permitted (#8100) - The log level of TLS handshake timeout or non-TLS record errors have been demoted to debug level to reduce noise (#8096) JetStream - Num pending is now only calculated on consumer leaders, avoiding unnecessary CPU usage on followers (#8172) - Snapshot and catchup loops no longer leak timers (#8186, thanks to @SebTardif) - Stream and consumer assignment errors are now surfaced (#8208) - Intersection of sublists and subject trees can now be cancelled early, avoiding high CPU usage in some pathological cases (#8209) ### Fixed General - Fixed a deadlock that could occur when processing cluster info hit Raft lock contention (#8080) - A number of sublists that incorrectly ignored the `disable_sublist_cache` option have been fixed (#8081) - Cluster route compression now obeys the cluster `max_pings_out` option if configured (#8093) - The internal send loop no longer mutates caller headers, which could corrupt buffers (#8097) - Removing headers no longer fails to remove later headers if the matching prefix also appeared in an earlier header value (#8103) - The sublist now correctly maintains negative results in the cache when calculating number of interested subjects (#8119) - Server shutdown requests are now idempotent, preventing concurrency issues when shutting down in embedded contexts (#8163) - TLS listeners now work correctly with the PROXY protocol where enabled (#8130) - Reduced lock contention that could be created between leafnodes and clients (#8139, #8159) - Fixed a panic that could happen when an error occurs when walking JWT directory resolver folders (#8173, thanks to @SebTardif) - In-process connections will no longer unexpectedly revert to TLS required with async `INFO` (#8205) Leafnodes - Leafnode connections will no longer negotiate compression if they are configured over already-compressed WebSockets (#7969) JetStream - Atomic batch now sends an unsupported advisory on API level mismatch (#8082) - A bug which corrupted message schedule subjects on recovery has been fixed (#8085) - Reduced lock contention on node leader changes and Raft group creation (#8087) - Fixed a protocol error that could be caused by double-encoding of `$JS.ACK` reply subjects over routes or gateways (#8089) – Fixed a panic that could occur when decoding a truncated Raft append entry from the wire (#8092) - Atomic batch no longer double-pools committed entries on cleanup (#8098) - Raft nodes will now ignore temporary snapshots on recovery after a crash (#8101) - A number of paths that could leave consumer redelivered in a drifted state have been fixed, e.g. with workqueue or interest-based streams with `max_deliver`, on single message removal or after purges/compactions (#8102) - Caches are now cleared correctly when converting filestore encryption mode, avoiding block-level corruption (#8105, #8166) - Fixed a race condition when updating the deduplication map on leader change (#8106) - Source consumer creation will no longer schedule a recreation if a setup is already in progress, avoiding potential setup storms (#8111) - Fixed data races when reading from the stream configuration when checking reservations, answering some API requests amongst others (#8115) - Stream republish subjects are now validated correctly (#8127) - The delivery policy for consumers on clustered workqueue streams is now enforced correctly (#8126) - Raft node append entry caches are now invalidated correctly on WAL truncation and snapshot installs (#8149) - Skip message errors are now surfaced correctly, propagating failures (#8152) - Mirror consumers are now retried immediately on a last sequence mismatch, avoiding stalling for longer than necessary (#8152) - Raft nodes will no longer allow proposals to remove unknown peers (#8154) - Pending state no longer leaks when reaching max deliveries (#8156) - A panic when reusing a wait group when resetting a stream's clustered state has been fixed (#8158) - Correctly reset local meta log when extending the meta group to a parent domain (#8142) - Consumer file stores will now correctly flush when deleting a single redelivery, avoiding unexpected further redeliveries (#8168) - Storage reservations for un-tiered streams have been made consistent between creates/updates and clustered/non-clustered modes (#8170) - Raft will now correctly cancel an in-flight checkpoint operation when resetting (#8180, #8202) - The `JetStreamMaxMemory` and `JetStreamMaxStore` options are now handled correctly in embedded mode (#8184) - A number of fields that were aliasing underlying filestore block caches have been fixed (#8187) - Consumers with `inactive_threshold` should no longer have their local state deleted unexpectedly when the proposal to the metalayer to clean up the consumer fails (#8198) - Metalayer state is now preserved in a number of cases where it was incorrectly being removed on shutdown (#8199) MQTT - Invalid characters in subjects are now rejected correctly, avoiding protocol issues when forwarded to other connection types (#8104, #8112) ### Complete Changes https://github.com/nats-io/nats-server/compare/v2.12.8...v2.12.9