12 KiB
nats.rs: Overview and Architecture
Version: async-nats 0.49.1, nats-server 0.1.0
Repository: https://github.com/nats-io/nats.rs
License: Apache-2.0
Rust Edition: 2021
MSRV: 1.88.0
Protocol: NATS Client Protocol (INFO/CONNECT/PUB/SUB/UNSUB/PING/PONG)
What It Is
The nats.rs repository contains the official Rust client for NATS.io, a high-performance messaging system. The active crate is async-nats — a fully async, Tokio-based NATS client. The deprecated nats crate (synchronous) receives security fixes only.
The nats-server crate is not an implementation of the NATS server. It is a test harness that spawns the Go-based nats-server binary for integration tests. The actual NATS server is a separate Go project at github.com/nats-io/nats-server.
Core design decisions:
- Fully async — all I/O is Tokio-based with async/await throughout
- Cloneable Client handle —
Clientis cheap to clone (Arc internals), all protocol work happens in a singleConnectionHandlertask - Channel-based internal communication —
ClientsendsCommandvariants viampscchannel toConnectionHandler - Multiplexed request-reply — one internal subscription handles all request-response patterns via inbox token routing
- Automatic reconnection — exponential backoff with configurable server pool rotation
- Feature-gated subsystems — JetStream, KV, Object Store, Service API, NKeys, WebSockets, and crypto backends are all optional
Workspace Structure
nats.rs/
├── async-nats/ # Primary crate — async NATS client
│ ├── src/
│ │ ├── lib.rs # Entry point: connect(), ServerOp, ClientOp, Command, ConnectionHandler, Subscriber
│ │ ├── client.rs # Client handle: publish, subscribe, request, flush, drain
│ │ ├── connection.rs # Low-level I/O: protocol parsing, read/write buffers
│ │ ├── connector.rs # Connection establishment, reconnection, server pool
│ │ ├── options.rs # ConnectOptions builder
│ │ ├── auth.rs # Auth struct (credentials container)
│ │ ├── auth_utils.rs # Credential file parsing (.creds files)
│ │ ├── error.rs # Generic Error<Kind> type
│ │ ├── header.rs # HeaderMap — NATS message headers
│ │ ├── subject.rs # Subject type, ToSubject trait
│ │ ├── status.rs # StatusCode (100-999 NATS protocol codes)
│ │ ├── message.rs # Message and OutboundMessage types
│ │ ├── tls.rs # TLS configuration helpers
│ │ ├── crypto.rs # Crypto feature support
│ │ ├── id_generator.rs # NUID/rand-based unique ID generation
│ │ ├── datetime.rs # DateTime helpers for JetStream/Service
│ │ ├── jetstream/ # JetStream API (feature-gated)
│ │ │ ├── mod.rs # Module root, jetstream::new(), with_domain()
│ │ │ ├── context.rs # JetStream Context — streams, publishing, consumers
│ │ │ ├── stream.rs # Stream management, Config, Info, Consumer creation
│ │ │ ├── consumer/ # Pull, Push, Ordered consumers
│ │ │ ├── message.rs # JetStream Message with ack methods
│ │ │ ├── publish.rs # PublishAck
│ │ │ ├── response.rs # Response wrapper
│ │ │ ├── errors.rs # JetStream error codes
│ │ │ ├── account.rs # Account info
│ │ │ ├── kv/ # Key-Value store (feature: "kv")
│ │ │ └── object_store/ # Object store (feature: "object-store")
│ │ └── service/ # Service API (feature-gated)
│ │ ├── mod.rs # Service, ServiceBuilder
│ │ ├── endpoint.rs # Endpoint handling
│ │ └── error.rs # Service errors
│ ├── tests/ # Integration tests (require nats-server binary)
│ ├── examples/ # Runnable examples
│ └── benches/ # Criterion benchmarks
├── nats-server/ # Test harness — spawns Go nats-server for tests
│ ├── src/lib.rs # Server struct, run_server(), run_cluster()
│ └── configs/ # Server config files for tests
│ └── jetstream.conf
└── nats/ # DEPRECATED sync client — do not modify
Architecture Diagram
┌──────────────────────────────────────────────────────────┐
│ Application Layer │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ JetStream│ │ KV │ │ Object │ │ Service │ │
│ │ Context │ │ Store │ │ Store │ │ API │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └──────────────┴─────────────┴─────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Client │ Cloneable handle │
│ │ (mpsc::Sender) │
│ └──────┬──────┘ │
│ │ Command channel │
└──────────────────────────┼────────────────────────────────┘
│
┌──────────────────────────┼────────────────────────────────┐
│ ConnectionHandler │
│ (single Tokio task) │
│ │ │
│ ┌───────────┐ ┌───────┴───────┐ ┌──────────────────┐ │
│ │Subscriptions│ │ Multiplexer │ │ Flush Observers │ │
│ │ HashMap │ │ (request-reply)│ │ │ │
│ └──────┬──────┘ └───────┬───────┘ └──────────────────┘ │
│ └────────────────┼ │
│ ┌──────┴──────┐ │
│ │ Connector │ Server pool, reconnect │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ Connection │ Protocol I/O │
│ │ (read/write)│ ServerOp / ClientOp │
│ └──────┬──────┘ │
└──────────────────────────┼────────────────────────────────┘
│
┌──────┴──────┐
│ NATS Server │ (Go binary, TCP/TLS/WS)
└─────────────┘
Key Concepts
Subject
NATS uses subject strings for message addressing. A Subject is a validated, immutable, UTF-8 string backed by Bytes. Subjects use dot-delimited tokens (e.g., events.data.sensor1). Wildcards * (single token) and > (multi-token suffix) are supported for subscriptions.
ClientOp / ServerOp
The NATS client-server protocol is text-based with binary payloads. The client sends ClientOp variants (CONNECT, PUB/HPUB, SUB, UNSUB, PING, PONG) and receives ServerOp variants (INFO, MSG/HMSG, +OK, -ERR, PING, PONG).
Command
Internal command type sent from Client to ConnectionHandler via mpsc channel. Includes Publish, Request, Subscribe, Unsubscribe, Flush, Drain, Reconnect, SetServerPool, ServerPool.
Multiplexer
A single internal subscription (SID 0) that routes all request-reply responses. When a Request is made, a unique inbox token is registered in the multiplexer's sender map, and the response is dispatched to the corresponding oneshot::Sender.
ConnectionHandler
A single Tokio task that drives all protocol I/O. It processes server operations from Connection, handles client commands from the mpsc channel, manages subscriptions, maintains ping/pong health, and orchestrates reconnection.
nats-server Test Harness
The nats-server crate provides utilities for launching real NATS server instances in tests:
run_server(cfg)— starts a single server with optional configrun_cluster(cfg)— starts a 3-node clusterServerstruct — holds the child process, cleans up on dropServer::restart()— kills and restarts the server processServer::client_url()— reads the INFO from the server to get the client URLset_lame_duck_mode(server)— sends LDM signal to the server process
The test harness spawns the Go nats-server binary via std::process::Command, using dynamic ports for parallel test execution. It auto-discovers the client URL by connecting to the server's TCP port and parsing the INFO JSON. On Drop, it kills the child process and cleans up JetStream storage directories.
Feature Flags
# Default: everything enabled
default = ["server_2_10", "server_2_11", "server_2_12", "server_2_14",
"service", "ring", "jetstream", "nkeys", "crypto",
"object-store", "kv", "websockets", "nuid"]
# Subsystems
jetstream # JetStream API
kv # Key-Value store (requires jetstream)
object-store # Object store (requires jetstream + crypto)
service # Service API
# Crypto backends (pick one)
ring # Default crypto backend
aws-lc-rs # Alternative backend
fips # FIPS mode (requires aws-lc-rs)
# Auth
nkeys # NKey authentication
# Other
nuid # NUID-based ID generation (falls back to rand)
crypto # Encryption support
websockets # WebSocket transport
experimental # Experimental features
# Server version markers (enable version-specific API fields)
server_2_10
server_2_11
server_2_12
server_2_14
Dependencies (Key)
| Dependency | Purpose |
|---|---|
tokio |
Async runtime (macros, rt, net, sync, time, io-util) |
bytes |
Zero-copy byte buffers for payloads |
tokio-rustls |
TLS via rustls |
rustls-native-certs |
Load native TLS root certificates |
serde / serde_json |
JSON serialization for protocol messages and JetStream API |
memchr |
Fast CRLF search for protocol parsing |
futures-util |
Stream trait, Sink trait, StreamExt |
tracing |
Structured logging |
thiserror |
Error type derivation |
url |
URL parsing for server addresses |
portable-atomic |
Portable atomic operations |