Features

NUTS turns a NATS JetStream into a browser-friendly, replayable event stream — with the operational guard rails you need to run it in production.

Streaming

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.

Persistence & replay

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.

Security & auth

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.

Operations

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 503 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.

Deployment

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.