NATS Has a Free Messaging System That Replaces Kafka, RabbitMQ, and Redis Pub/Sub

# nats# messaging# kafka# microservices
NATS Has a Free Messaging System That Replaces Kafka, RabbitMQ, and Redis Pub/SubAlex Spinov

Kafka needs ZooKeeper and a team to manage it. RabbitMQ needs Erlang expertise. NATS is a single 20MB...

Kafka needs ZooKeeper and a team to manage it. RabbitMQ needs Erlang expertise. NATS is a single 20MB binary that handles pub/sub, queues, and streaming — with zero dependencies.

NATS vs Everything

Kafka RabbitMQ Redis Pub/Sub NATS
Binary size 300MB+ 100MB+ 10MB 20MB
Dependencies JVM, ZooKeeper Erlang None None
Setup time Hours 30 min 5 min 30 sec
Persistence Yes Yes No Yes (JetStream)
Operations Complex Medium Simple Simple
Latency ms ms sub-ms sub-ms

Install & Run

# Docker
docker run -p 4222:4222 nats:latest -js
# -js enables JetStream (persistence)

# Or binary
curl -L https://github.com/nats-io/nats-server/releases/latest/download/nats-server-linux-amd64.zip -o nats.zip
unzip nats.zip && ./nats-server -js
Enter fullscreen mode Exit fullscreen mode

Pub/Sub (Core NATS)

import { connect } from "nats";

const nc = await connect({ servers: "localhost:4222" });

// Subscribe
const sub = nc.subscribe("orders.created");
for await (const msg of sub) {
  const order = JSON.parse(new TextDecoder().decode(msg.data));
  console.log(`New order: ${order.id}`);
}

// Publish
nc.publish("orders.created", JSON.stringify({ id: "123", total: 99.99 }));
Enter fullscreen mode Exit fullscreen mode

Messages are fire-and-forget. No persistence. Sub-millisecond latency.

Request/Reply

// Service (responder)
const sub = nc.subscribe("user.lookup");
for await (const msg of sub) {
  const { userId } = JSON.parse(msg.data);
  const user = await db.findUser(userId);
  msg.respond(JSON.stringify(user));
}

// Client (requester)
const response = await nc.request("user.lookup", JSON.stringify({ userId: "123" }));
const user = JSON.parse(response.data);
Enter fullscreen mode Exit fullscreen mode

Built-in service discovery via request/reply. No service registry needed.

JetStream (Persistent Streaming)

import { connect, AckPolicy, DeliverPolicy } from "nats";

const nc = await connect({ servers: "localhost:4222" });
const js = nc.jetstream();
const jsm = await nc.jetstreamManager();

// Create stream
await jsm.streams.add({
  name: "ORDERS",
  subjects: ["orders.>"],
  retention: "limits",
  max_msgs: 1000000,
  max_age: 86400000000000, // 24 hours in nanoseconds
});

// Publish (persisted)
await js.publish("orders.created", JSON.stringify({ id: "456" }));

// Consume
const consumer = await js.consumers.get("ORDERS", "my-consumer");
const messages = await consumer.consume();
for await (const msg of messages) {
  console.log(JSON.parse(msg.data));
  msg.ack();
}
Enter fullscreen mode Exit fullscreen mode

JetStream = Kafka-like streaming without Kafka-like complexity.

Key-Value Store

const kv = await js.views.kv("config");

await kv.put("feature.dark-mode", "true");
const entry = await kv.get("feature.dark-mode");
console.log(entry?.string()); // "true"

// Watch for changes
const watch = await kv.watch();
for await (const entry of watch) {
  console.log(`${entry.key} = ${entry.string()}`);
}
Enter fullscreen mode Exit fullscreen mode

Distributed key-value store — like etcd but built into NATS.

Object Store

const os = await js.views.os("files");

// Store file
await os.put({ name: "report.pdf" }, readFileSync("report.pdf"));

// Retrieve
const result = await os.get("report.pdf");
Enter fullscreen mode Exit fullscreen mode

Store large objects across NATS clusters.


Need messaging infrastructure? I build distributed systems and data tools. Email spinov001@gmail.com or check my Apify tools.