NATS JetStream Cluster
High-performance messaging system with JetStream persistence and streaming.
Overview
NATS is a high-performance, cloud-native messaging system originally developed by Derek Collison in 2010, designed to provide extremely fast and lightweight communication for distributed systems. Unlike traditional message brokers, NATS focuses on simplicity and speed, delivering sub-millisecond latency with minimal resource overhead. JetStream, introduced as NATS 2.2's persistence layer, adds durability and streaming capabilities while maintaining NATS' performance characteristics. This cluster configuration creates a three-node NATS JetStream cluster that provides both high availability and data persistence, eliminating the single point of failure inherent in standalone deployments. The integration with Prometheus captures detailed metrics about message throughput, consumer lag, and cluster health, while Grafana transforms this telemetry into visual dashboards for real-time monitoring. The nats-box utility container provides a complete CLI toolkit for stream management, consumer testing, and administrative operations. This stack particularly excels in scenarios requiring both real-time messaging performance and guaranteed message delivery, making it ideal for financial trading platforms, IoT data ingestion, and microservices architectures where message loss is unacceptable but traditional heavyweight brokers introduce too much latency.
Key Features
- Three-node NATS cluster with automatic failover and split-brain protection
- JetStream persistence engine with configurable retention policies and storage limits
- Pull and push consumer patterns with acknowledgment-based delivery guarantees
- Stream replication across cluster nodes for data durability and availability
- Built-in monitoring endpoints exposing JetStream metrics and cluster topology
- Subject-based routing with wildcard support for flexible message distribution
- Queue groups for load balancing consumers across multiple application instances
- Real-time Grafana dashboards showing message rates, stream sizes, and consumer lag
Common Use Cases
- 1Financial trading systems requiring sub-millisecond message delivery with audit trails
- 2IoT sensor networks collecting telemetry data with guaranteed persistence
- 3Microservices architectures needing both request-reply and event streaming patterns
- 4Real-time chat applications with message history and offline delivery
- 5Log aggregation systems processing high-volume structured data streams
- 6Event-driven architectures implementing CQRS patterns with event sourcing
- 7Gaming backends managing player state synchronization and match coordination
Prerequisites
- Minimum 768MB RAM available (256MB per NATS node plus monitoring stack)
- Docker Engine 20.10+ with Docker Compose v2 for multi-container orchestration
- Ports 4222, 8222, 9090, and 3000 available on the host system
- Basic understanding of pub/sub messaging patterns and stream processing concepts
- Familiarity with PromQL for customizing Prometheus monitoring queries
- SSD storage recommended for JetStream data volumes to ensure optimal performance
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 nats1: 3 image: nats:latest4 hostname: nats15 ports: 6 - "4222:4222"7 - "8222:8222"8 command: >9 -js10 -sd /data11 -cluster nats: //0.0.0.0:622212 -cluster_name nats-cluster13 -routes nats: //nats2:6222,nats://nats3:622214 -m 822215 volumes: 16 - nats1_data:/data17 networks: 18 - nats-net19 restart: unless-stopped2021 nats2: 22 image: nats:latest23 hostname: nats224 command: >25 -js26 -sd /data27 -cluster nats: //0.0.0.0:622228 -cluster_name nats-cluster29 -routes nats: //nats1:6222,nats://nats3:622230 volumes: 31 - nats2_data:/data32 networks: 33 - nats-net34 restart: unless-stopped3536 nats3: 37 image: nats:latest38 hostname: nats339 command: >40 -js41 -sd /data42 -cluster nats: //0.0.0.0:622243 -cluster_name nats-cluster44 -routes nats: //nats1:6222,nats://nats2:622245 volumes: 46 - nats3_data:/data47 networks: 48 - nats-net49 restart: unless-stopped5051 nats-box: 52 image: natsio/nats-box:latest53 command: sleep infinity54 depends_on: 55 - nats156 networks: 57 - nats-net5859 prometheus: 60 image: prom/prometheus:latest61 ports: 62 - "9090:9090"63 volumes: 64 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro65 - prometheus_data:/prometheus66 networks: 67 - nats-net68 restart: unless-stopped6970 grafana: 71 image: grafana/grafana:latest72 ports: 73 - "3000:3000"74 environment: 75 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}76 volumes: 77 - grafana_data:/var/lib/grafana78 depends_on: 79 - prometheus80 networks: 81 - nats-net82 restart: unless-stopped8384volumes: 85 nats1_data: 86 nats2_data: 87 nats3_data: 88 prometheus_data: 89 grafana_data: 9091networks: 92 nats-net: 93 driver: bridge.env Template
.env
1# NATS Configuration2NATS_CLUSTER_NAME=nats-cluster34# Grafana5GRAFANA_PASSWORD=secure_grafana_passwordUsage Notes
- 1NATS client connection at localhost:4222
- 2Monitoring endpoint at http://localhost:8222
- 3Use nats-box: docker compose exec nats-box nats
- 4JetStream enabled for persistence
Individual Services(6 services)
Copy individual services to mix and match with your existing compose files.
nats1
nats1:
image: nats:latest
hostname: nats1
ports:
- "4222:4222"
- "8222:8222"
command: |
-js -sd /data -cluster nats://0.0.0.0:6222 -cluster_name nats-cluster -routes nats://nats2:6222,nats://nats3:6222 -m 8222
volumes:
- nats1_data:/data
networks:
- nats-net
restart: unless-stopped
nats2
nats2:
image: nats:latest
hostname: nats2
command: |
-js -sd /data -cluster nats://0.0.0.0:6222 -cluster_name nats-cluster -routes nats://nats1:6222,nats://nats3:6222
volumes:
- nats2_data:/data
networks:
- nats-net
restart: unless-stopped
nats3
nats3:
image: nats:latest
hostname: nats3
command: |
-js -sd /data -cluster nats://0.0.0.0:6222 -cluster_name nats-cluster -routes nats://nats1:6222,nats://nats2:6222
volumes:
- nats3_data:/data
networks:
- nats-net
restart: unless-stopped
nats-box
nats-box:
image: natsio/nats-box:latest
command: sleep infinity
depends_on:
- nats1
networks:
- nats-net
prometheus
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
- nats-net
restart: unless-stopped
grafana
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
volumes:
- grafana_data:/var/lib/grafana
depends_on:
- prometheus
networks:
- nats-net
restart: unless-stopped
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 nats1:5 image: nats:latest6 hostname: nats17 ports:8 - "4222:4222"9 - "8222:8222"10 command: >11 -js12 -sd /data13 -cluster nats://0.0.0.0:622214 -cluster_name nats-cluster15 -routes nats://nats2:6222,nats://nats3:622216 -m 822217 volumes:18 - nats1_data:/data19 networks:20 - nats-net21 restart: unless-stopped2223 nats2:24 image: nats:latest25 hostname: nats226 command: >27 -js28 -sd /data29 -cluster nats://0.0.0.0:622230 -cluster_name nats-cluster31 -routes nats://nats1:6222,nats://nats3:622232 volumes:33 - nats2_data:/data34 networks:35 - nats-net36 restart: unless-stopped3738 nats3:39 image: nats:latest40 hostname: nats341 command: >42 -js43 -sd /data44 -cluster nats://0.0.0.0:622245 -cluster_name nats-cluster46 -routes nats://nats1:6222,nats://nats2:622247 volumes:48 - nats3_data:/data49 networks:50 - nats-net51 restart: unless-stopped5253 nats-box:54 image: natsio/nats-box:latest55 command: sleep infinity56 depends_on:57 - nats158 networks:59 - nats-net6061 prometheus:62 image: prom/prometheus:latest63 ports:64 - "9090:9090"65 volumes:66 - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro67 - prometheus_data:/prometheus68 networks:69 - nats-net70 restart: unless-stopped7172 grafana:73 image: grafana/grafana:latest74 ports:75 - "3000:3000"76 environment:77 - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}78 volumes:79 - grafana_data:/var/lib/grafana80 depends_on:81 - prometheus82 networks:83 - nats-net84 restart: unless-stopped8586volumes:87 nats1_data:88 nats2_data:89 nats3_data:90 prometheus_data:91 grafana_data:9293networks:94 nats-net:95 driver: bridge96EOF9798# 2. Create the .env file99cat > .env << 'EOF'100# NATS Configuration101NATS_CLUSTER_NAME=nats-cluster102103# Grafana104GRAFANA_PASSWORD=secure_grafana_password105EOF106107# 3. Start the services108docker compose up -d109110# 4. View logs111docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/nats-jetstream-cluster/run | bashTroubleshooting
- Cluster formation fails with 'no route to host': Ensure all NATS containers can resolve each other's hostnames and verify the nats-net network is created properly
- JetStream consumers show increasing lag: Check if consumer acknowledgment timeouts are too short or if processing applications have crashed using 'nats consumer info'
- Memory usage grows unbounded: Configure stream retention policies with max_msgs or max_bytes limits to prevent infinite message accumulation
- Split-brain scenario with multiple leaders: Restart all NATS containers simultaneously to force cluster re-election and check for network partitioning issues
- Prometheus shows gaps in NATS metrics: Verify that port 8222 monitoring endpoint is accessible and confirm prometheus.yml includes all NATS node targets
- Messages lost during node restart: Ensure JetStream streams have replication factor set to 3 using 'nats stream add --replicas=3' for full cluster redundancy
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Components
natsnats-boxprometheusgrafana
Tags
#nats#jetstream#messaging#streaming#high-performance
Category
Message Queues & BrokersAd Space
Shortcuts: C CopyF FavoriteD Download