A pinned consumer policy mismatch alert fires when a JetStream consumer has the io.nats.monitor.pinned metadata key set but its priority_policy is not configured to overflow. This indicates that the operator intends the consumer to behave as a pinned consumer — where one subscriber is the designated primary and others serve as overflow backups — but the consumer configuration doesn’t enforce this behavior. Without the overflow priority policy, all subscribers receive messages via standard distribution, defeating the purpose of the pinned designation.
Pinned consumers are a specialized pattern for workloads that require ordered, single-subscriber processing with automatic failover. The pattern works by designating one subscriber as the “pinned” primary that receives all messages, while additional subscribers wait in standby. If the primary disconnects or becomes unhealthy, an overflow subscriber takes over immediately. This ensures processing continues without interruption while maintaining the ordering guarantees that come from single-subscriber delivery.
The overflow priority policy is the mechanism that enforces this behavior. Without it, the consumer distributes messages across all subscribers using round-robin or other standard distribution logic. This means:
The metadata annotation signals operator intent: “this consumer should be pinned.” The priority policy enforces it at the infrastructure level. When these two are out of sync, the system behaves differently from what the operator expects, which can lead to subtle data processing errors that are difficult to diagnose after the fact.
This mismatch often occurs during consumer migration or when teams copy consumer configurations between environments without preserving all settings. The metadata gets carried over but the priority policy — which may require a specific server version or configuration syntax — gets dropped.
Consumer created before priority_policy support. The operator added the io.nats.monitor.pinned metadata to mark their intent, but the NATS server version at the time didn’t support priority_policy. After upgrading the server, the consumer configuration was never updated to add the policy.
Configuration template missing the priority_policy field. Infrastructure-as-code templates (Terraform, Helm, Pulumi) define the consumer with metadata but omit the priority_policy field. Every consumer created from the template has the mismatch.
Consumer edited and policy dropped. When updating a consumer configuration (changing ack_wait, filter subject, etc.), the priority_policy was accidentally removed. Some CLI or API workflows require specifying the full configuration on update, and omitting a field resets it to the default.
Manual consumer creation with incomplete configuration. An operator creates a consumer via the CLI or API and adds the metadata but forgets to set priority_policy=overflow. The metadata is documentation-level; it doesn’t automatically configure the priority behavior.
Environment-specific configuration drift. The consumer is correctly configured in production but a staging or development environment has a copy that lacks the priority policy. The metadata matches across environments but the behavior differs.
nats consumer info STREAM_NAME CONSUMER_NAME -j | \ jq '{metadata: .config.metadata, priority_policy: .config.priority_policy}'If the output shows io.nats.monitor.pinned in metadata but priority_policy is null or absent, the mismatch is confirmed.
# Find all consumers across streams that have pinned metadatafor stream in $(nats stream list -n); do for consumer in $(nats consumer list "$stream" -n); do result=$(nats consumer info "$stream" "$consumer" -j 2>/dev/null | \ jq -r 'select(.config.metadata["io.nats.monitor.pinned"] != null) | "\(.stream_name)/\(.name): priority_policy=\(.config.priority_policy // "NOT SET")"') [ -n "$result" ] && echo "$result" donedoneThis shows all consumers marked as pinned and whether their priority policy is correctly configured.
nats server report jetstreamThe priority_policy feature requires NATS Server 2.11 or later. If your servers are on an older version, the policy cannot be set even if the metadata is present.
1// Go: detect pinned metadata without overflow policy.2// PriorityPolicy lives in github.com/nats-io/nats.go/jetstream — the3// legacy nats.JetStreamContext API does not expose it.4import (5 "context"6 "fmt"7
8 "github.com/nats-io/nats.go"9 "github.com/nats-io/nats.go/jetstream"10)11
12ctx := context.Background()13js, _ := jetstream.New(nc)14stream, _ := js.Stream(ctx, "STREAM_NAME")15
16consumers := stream.ListConsumers(ctx)17for ci := range consumers.Info() {18 _, hasPinned := ci.Config.Metadata["io.nats.monitor.pinned"]19 if hasPinned && ci.Config.PriorityPolicy != jetstream.PriorityPolicyOverflow {20 fmt.Printf("MISMATCH: %s/%s has pinned metadata but priority_policy=%v\n",21 ci.Stream, ci.Name, ci.Config.PriorityPolicy)22 }23}1# Python: detect pinned consumer policy mismatch2import nats3
4nc = await nats.connect()5js = nc.jetstream()6
7consumers = await js.consumers_info("STREAM_NAME")8for ci in consumers:9 metadata = ci.config.metadata or {}10 if "io.nats.monitor.pinned" in metadata:11 policy = getattr(ci.config, "priority_policy", None)12 if policy != "overflow":13 print(f"MISMATCH: {ci.stream_name}/{ci.name} "14 f"has pinned metadata but priority_policy={policy}")The fix is to add (or correct) the priority_policy on the consumer configuration:
nats consumer edit STREAM_NAME CONSUMER_NAME --priority-policy overflowIf the consumer needs to also specify a priority group (to coordinate across multiple consumers), set the group as well:
nats consumer edit STREAM_NAME CONSUMER_NAME \ --priority-policy overflow \ --priority-groups "pinned-group-1"After updating, confirm the configuration is correct:
nats consumer info STREAM_NAME CONSUMER_NAME -j | \ jq '{metadata: .config.metadata, priority_policy: .config.priority_policy, priority_groups: .config.priority_groups}'Both io.nats.monitor.pinned metadata and priority_policy: "overflow" should be present.
If consumers are managed via Terraform, Helm, or other IaC tools, update the template to include the priority policy:
1# Terraform example2resource "jetstream_consumer" "pinned_processor" {3 stream_id = jetstream_stream.orders.id4
5 durable_name = "pinned-processor"6 ack_policy = "explicit"7 priority_policy = "overflow"8
9 metadata = {10 "io.nats.monitor.pinned" = "true"11 }12}Upgrade to NATS Server 2.11 or later. If an immediate upgrade isn’t possible, remove the io.nats.monitor.pinned metadata to suppress the mismatch alert — but be aware that the consumer won’t behave as a pinned consumer until the policy can be applied:
# Remove pinned metadata if overflow policy isn't available yetnats consumer edit STREAM_NAME CONSUMER_NAME \ --metadata "io.nats.monitor.pinned="Add validation to your consumer creation workflow. Any process that sets io.nats.monitor.pinned metadata should also set priority_policy=overflow. This can be enforced via CI checks on IaC templates or wrapper scripts around consumer creation.
Use Synadia Insights for ongoing drift detection. Insights evaluates this check across all consumers every collection epoch, catching mismatches introduced by manual changes, failed deployments, or configuration drift between environments.
The overflow priority policy ensures that messages are delivered to the highest-priority subscriber first. If that subscriber is unavailable (disconnected or slow), messages “overflow” to the next subscriber in priority order. This creates a primary/standby pattern where one subscriber handles all messages under normal conditions, and backups take over automatically during failures.
Yes. Pinned consumers with the overflow priority policy work with pull-based consumers. The priority determines which subscriber’s fetch requests are fulfilled first. If the primary subscriber stops fetching, the overflow subscriber’s pending fetch requests receive messages instead.
The consumer exists but no messages are delivered (no subscribers to deliver to). The pinned metadata and priority policy only affect delivery behavior when subscribers are present. The consumer simply accumulates pending messages in the stream.
No. You can set priority_policy=overflow without the io.nats.monitor.pinned metadata. The metadata is used by monitoring tools like Synadia Insights to verify that the operator’s intent (pinned behavior) matches the configuration (overflow policy). Setting the policy without the metadata is valid but means monitoring tools won’t flag the consumer for this specific consistency check.
Priority groups are used when multiple consumers on the same stream coordinate their pinned behavior. Subscribers within the same priority group share the overflow failover logic. If you have a single pinned consumer, a single group suffices. For complex topologies with multiple pinned consumers handling different subject partitions, use distinct group names to keep their failover logic independent.
The consumer configuration update may briefly interrupt delivery as the consumer’s internal state is updated. Active subscribers will reconnect and resume. Plan the change during a low-traffic period if the consumer processes latency-sensitive workloads, though the disruption is typically subsecond.
With 100+ always-on audit Checks from the NATS experts, Insights helps you find and fix problems before they become costly incidents.
No alert rules to write. No dashboards to maintain.
News and content from across the community