Everything, baked in
NUTS turns a NATS JetStream into a browser-friendly, replayable event stream — with the operational guard rails you need to run it in production.
Push the moment it happens
Real-time SSE
Stream NATS messages directly to browsers using the standard EventSource API. No WebSocket bridge, no polling, no client SDK.
Multiple topics per connection
Subscribe to several NATS subjects in a single SSE stream via repeated ?topic= params or path-based shorthand.
Topic prefixing
Apply a server-side topic_prefix so clients use friendly names while NUTS subscribes to the fully-qualified NATS subjects.
Heartbeat keep-alives
Configurable heartbeat frames keep idle connections open through proxies and CDNs.
Durable by default, resumable by design
JetStream-backed durability
Messages live in JetStream — NUTS just routes them to subscribers, so retention, deduplication, and storage policies stay in NATS.
Resumable streams
Reconnecting clients pick up exactly where they left off using ?last-id= or the standard Last-Event-ID header. Browser EventSource sends the header for free.
Replay storm guards
Bound large catch-ups with replay_max_messages and replay_window so a single stale client can't drag the server through tens of thousands of historical events.
No silent message loss
Slow clients are disconnected before queued messages are dropped — they reconnect with their last event ID and resume cleanly.
Locked down, edge to broker
JWT subscriber auth
HMAC-signed JWTs with per-topic subscribe claims, accepted from Authorization: Bearer or a configurable cookie for browser EventSource clients.
NATS authentication
Connect to NATS using credentials files, tokens, or user/password — keep the broker secured independently of subscriber auth.
NATS TLS & mTLS
Optional nats_tls_ca, nats_tls_cert, and nats_tls_key directives for encrypted, mutually authenticated NATS connections.
CORS done right
Echoes Origin from the allow-list, adds Vary: Origin, and only advertises credentials for explicitly listed origins — no accidental wildcard credential leaks.
Observable and safe to run
Prometheus metrics
Built-in nuts_* counters and gauges — active connections, messages delivered, slow-client disconnects, replay stats, rejected connections, and more.
Liveness & readiness probes
Separate /livez and /readyz endpoints for Kubernetes probes and load-balancer health checks — readiness actually verifies the NATS connection and stream.
Connection caps
max_connections bounds concurrent SSE streams; rejected clients receive 429 with Retry-After instead of degrading the whole instance.
Per-frame write bounds
Optional dispatch_timeout and write_timeout keep slow downstream connections from tying up a handler indefinitely.
Hub discovery
Optional Link header with rel="nuts" lets clients discover the hub URL automatically from any response that carries it.
Structured logs
Every stream emits structured fields — topics, subjects, replay_mode, disconnect_reason — ready for log aggregation and incident response.
Ship it your way
Caddy native
First-class Caddy module — install with xcaddy, configure via Caddyfile or JSON, and inherit Caddy's TLS and routing.
Prebuilt Docker image
Multi-arch idcttech/nuts image on Docker Hub for amd64 and arm64 — mount a Caddyfile and go.
Compose-ready
Reference docker-compose.yml in the repo brings up NATS with JetStream and NUTS together for local development.
Ready to wire it up?
Build with xcaddy or pull the Docker image — you'll be streaming in minutes.