Platform: State Sync Setup

State Synchronization Setup (NATS + JetStream)

This guide walks you through enabling global state synchronization for health and membership across multiple gslbd instances using NATS with JetStream.

Overview

  • Each node publishes local health and heartbeats to NATS subjects and KV buckets.

  • Health state changes (healthy→unhealthy or unhealthy→healthy) are pushed immediately to NATS peers — peer convergence latency is under 200 ms regardless of checkInterval. A 30 s catchup ticker republishes the full snapshot in the background to recover from any missed signals.

  • Each node subscribes to the cluster subjects and KV snapshots to maintain a global view (GlobalHealthView).

  • The load balancer uses a composite provider to merge local and global health according to policy.

When to enable

  • You run multiple GSLB nodes across regions and want them to share health state.

  • You want quorum-based decisions or fast propagation of health changes.

Prerequisites

  • NATS 2.x with JetStream enabled.

  • TLS/mTLS credentials for clients (recommended).

  • A cluster ID configured in gslbd.

Recommended topology (super-cluster)

  • 3+ NATS servers per region (odd number for availability).

  • Connect regions via NATS gateways to form a super-cluster.

  • Enable JetStream in each cluster; optionally set a JetStream domain (e.g., gslb).

Minimal NATS server (single region) example

# nats-server.conf (excerpt)
jetstream: {
domain: gslb
}
server_name: n1
port: 4222
cluster: {
name: gslb
port: 6222
}
# TLS, accounts, and gateways omitted for brevity; see NATS docs

Configure gslbd Add to /etc/gslb/config.yaml:

cluster:
id: "prod-global"
 
state:
healthPolicy: "prefer-local" # or global-any-healthy | global-quorum
quorumMinPercent: 51 # used for global-quorum
heartbeatInterval: "10s"
heartbeatTTL: "30s"
nats:
servers: ["nats://n1.example.com:4222","nats://n2.example.com:4222","nats://n3.example.com:4222"]
tls:
caFile: "/etc/gslb/pki/ca.crt"
certFile: "/etc/gslb/pki/client.crt"
keyFile: "/etc/gslb/pki/client.key"
jetStream:
domain: "gslb"

!!! note "NATS is ephemeral-only" State sync over NATS covers health and membership only — ephemeral, TTL'd data. Configuration and data-plane objects are not synced over NATS: config flows from git via GitOps self-restart, and pools/members/services/users are replicated by the rqlite datastore (Raft). The old JetStream config-sync (enableConfigSync, NEXUS_CFG) has been removed. See State Sync reference.

Policies explained

  • local-or-global-fallback (default): use local health, falling back to the global view.

  • prefer-local: local result is authoritative; global used mainly for hints.

  • local-only: ignore global state (useful during incidents or testing).

  • global-any-healthy: consider healthy if any site reports healthy.

  • global-quorum: healthy only if a percent of active members report healthy within staleness TTL.

How quorum works

  • Each node publishes periodic heartbeats.

  • Active membership = nodes whose latest heartbeat is within heartbeatTTL.

  • For an endpoint, only reports from active members within heartbeatTTL are counted.

  • quorumMinPercent computes healthy threshold: healthy*100/total >= quorumMinPercent.

Verifying connectivity and state

  • Metrics to watch:

    • gslbd_state_nats_connected (1 when connected)

    • gslbd_state_active_members

    • gslbd_state_nats_{published,received}_total{type}

    • gslbd_state_kv_{put,get}_total{bucket,result}

    • gslbd_state_merge_lag_ms — histogram of NATS transit latency from publish to peer receipt; p95 > 500 ms indicates network issues between nodes

    • gslbd_health_failover_detection_seconds{direction} — Layer 1 detection latency per state change on this node; direction="down" is healthy→unhealthy

  • When Configuration Sync is enabled, logs will include messages like: config snapshot loaded and config event: cluster=... version=....

  • Logs will show connect errors or KV bucket creation errors.

Failure modes

  • If NATS is unreachable: gslbd continues with local health only (policy prefer-local).

  • If clocks skew: events include timestamps; quorum logic tolerates within TTL but keep NTP enabled.

  • If membership is zero: no quorum can be established; provider falls back to local (for global-quorum).

Security

  • Use mTLS for client/server auth or NATS accounts/JWT with TLS.

  • Restrict subjects and KV permissions to the cluster namespace (e.g., gslb.<cluster>.*).

  • Rotate client certs periodically; see Security Guide.


Was this article helpful?