// OSSeva Blog
OperationsKafka vs NATS (and JetStream): Design, Delivery, Performance and Where RabbitMQ Fits
The short answer
NATS is a messaging fabric for services; Kafka is a log for events. Core NATS routes messages by subject, with publish-subscribe, request and reply, and load-balanced queue groups built in, and it keeps nothing: delivery is at most once, to whoever is listening. JetStream, built into the same server, adds streams on memory or disk, acknowledgements, replay and replication. Kafka starts from the other end: every event is written to a partitioned, replicated log on disk, kept for its retention period, and read by consumer groups that track their own position. Choose NATS when you need service-to-service messaging, request and reply, edge or multi-tenant deployments, and moderate persistence in one small server. Choose Kafka when the events are a durable record that many systems consume and replay, and when its connector and stream-processing ecosystem matters. Choose RabbitMQ when you need a broker with flexible routing, per-message acknowledgement and dead-lettering for task and integration queues.
Kafka vs NATS vs RabbitMQ at a glance
| Apache Kafka | NATS (Core and JetStream) | RabbitMQ | |
|---|---|---|---|
| Model | Partitioned, replicated event log | Subject-based messaging; JetStream streams for persistence | Broker with exchanges, queues and streams |
| Default delivery | At-least-once; exactly-once between Kafka topics with transactions | Core: at most once. JetStream: at least once, with an exactly-once option | At-least-once with acknowledgements and publisher confirms |
| Storage | Log segments on disk; optional remote tier | Core: none. JetStream: memory or file per stream | Quorum queues and streams on disk |
| Replication | Per partition, across brokers | JetStream: 1 to 5 replicas per stream, RAFT-based | Raft-based quorum queues and streams |
| Request and reply | Built by the application on topics | Built in | Direct reply-to |
| Work queues | Share groups (production-ready in 4.2) | Queue groups; JetStream work-queue streams | Core use case |
| Replay | By offset, within retention | JetStream: by sequence, time or last message per subject | Streams only |
| Protocols | Kafka protocol | NATS protocol; MQTT 3.1.1 and WebSocket | AMQP 0-9-1, AMQP 1.0, MQTT, STOMP |
| Written in | Java and Scala | Go | Erlang |
| Licence and home | Apache 2.0, Apache Software Foundation | Apache 2.0, CNCF project | MPL 2.0, Broadcom |
How NATS works
Core NATS is publish-subscribe on subjects such as orders.created, with wildcards for subscribers. Many publishers and many subscribers can share a subject by default, a requester can send a message and wait for a reply on a private inbox, and subscribers that join the same queue group share the messages between them, which gives load balancing without a separate load balancer. The NATS documentation describes Core NATS delivery as "best-effort, at-most-once": if no one is subscribed, or a subscriber is disconnected, the message is gone.
JetStream is the persistence layer built into nats-server. A stream captures messages from one or more subjects and stores them in memory or on disk, with limits on age, size and message count, and a discard policy for when a limit is hit. Retention can be by limits (keep for replay), as a work queue (remove once consumed) or by interest (keep while consumers still need it). Consumers are server-side views of a stream that track progress and can replay from a sequence number, a time, or the last message per subject. Streams replicate across servers using a RAFT-based protocol, with 1 to 5 replicas; the docs recommend 3 as the usual balance. JetStream also provides a key/value store and an object store built on streams.
Two details matter when you compare durability. First, file-based streams are written to the operating system immediately but fsynced on an interval, two minutes by default, so the NATS docs explain the window for loss in an OS crash and offer sync_interval: always for the strongest guarantee, at a performance cost. Second, JetStream's exactly-once option relies on the publisher attaching a message ID that the server de-duplicates within a configured window, plus a double acknowledgement on the consumer side.
How Kafka differs
Kafka keeps the events instead of routing them. Topics are split into partitions spread across brokers, records with the same key always land in the same partition, and a consumer reads a partition in exactly the order it was written. Events stay after they are read until retention removes them, and each consumer group keeps its own offset, so new consumers can read history and old ones can rewind. A write is committed once every in-sync replica of the partition has it. Transactions give exactly-once processing between Kafka topics, which is how Kafka Streams works, and Kafka Connect is a framework for connectors that move data between Kafka and databases or other systems. Kafka has no request and reply primitive: applications build it with correlation IDs and reply topics.
Kafka vs NATS JetStream
This is the comparison most teams actually face, because JetStream is what gives NATS persistence and replay.
- Unit of scale. Kafka scales a topic by adding partitions and spreading them across brokers. A JetStream stream is replicated as a group of servers with one leader; you scale out by using more streams and placing them across the cluster.
- Retention. Both keep data by age or size. Kafka is built for long retention on disk and can move older segments to remote storage. JetStream supports long retention too, and adds work-queue and interest retention that delete messages once they are consumed.
- Consumption. Kafka consumers pull and manage offsets per partition. JetStream consumers are stateful objects on the server, either pulled by clients or pushed to a subject, with per-message acknowledgement and redelivery.
- Operations. NATS runs as one server process with JetStream switched on in configuration. Kafka runs brokers and KRaft controllers, and Kafka 4.0 removed ZooKeeper entirely.
- Ecosystem. Kafka's connectors, Kafka Streams and the many processing engines that read Kafka topics are its strongest argument. NATS's strongest arguments are request and reply, multi-tenancy through accounts, leaf nodes for edge sites and MQTT support in the same server.
RabbitMQ vs NATS
RabbitMQ is a broker: publishers send to exchanges, bindings route messages to queues by key, topic pattern or headers, and consumers acknowledge each message. Quorum queues replicate through Raft, dead-letter exchanges catch rejected or expired messages, and streams add a replayable log. NATS routes by subject with no exchange layer, and its persistence, acknowledgements and work queues come from JetStream. Choose RabbitMQ when routing rules, dead-lettering, priorities and AMQP or STOMP clients are central. Choose NATS when most traffic is request and reply or fan-out between services, when you need many isolated tenants on one cluster, or when the same messaging layer has to reach edge locations. For RabbitMQ against the other two, see Kafka vs RabbitMQ.
Kafka vs NATS performance
We do not quote benchmark numbers, because results depend on message size, persistence, acknowledgement mode and replication settings far more than on the product name. The designs tell you where each is strong. Core NATS keeps no state and does not wait for acknowledgements, so it is built for low latency between connected services, at the price of at-most-once delivery. JetStream adds acknowledged writes, replication and, if you choose, an fsync on every message, and each of those costs latency. Kafka batches records into an append-only log, serves consumers from the page cache without copying data through the application, and spreads load across partitions, which favours sustained throughput and many readers of the same data. Compare like with like: Core NATS against a fire-and-forget Kafka producer is a different test from JetStream with three replicas against Kafka with a replication factor of 3.
Which should you choose?
- Choose Kafka for event streaming and data pipelines: change data capture, analytics feeds, event sourcing, anything several teams consume and replay, and anything that needs Kafka Connect or a stream processor.
- Choose NATS for service-to-service messaging and request and reply, for edge and IoT deployments that need a small footprint, and for multi-tenant platforms. Add JetStream where messages must survive restarts.
- Choose RabbitMQ for task queues and integration work that needs routing, per-message acknowledgement, dead-lettering and standard protocols such as AMQP and STOMP.
- Use more than one where the estate has both kinds of traffic. Many do.
Where OSSeva fits
OSSeva does not support NATS. If NATS is the right choice for your workload, choose it and look for support elsewhere; we would rather say so than stretch our coverage. OSSeva supports the other two. OSSeva for Apache Kafka ships patched builds from 2.8 through 3.9 and covers 4.x in KRaft mode, and OSSeva for RabbitMQ covers 3.8 through 4.3, including community lines that no longer receive fixes, along with the Erlang/OTP runtime underneath. You keep the binaries you run today and change who supports them, under one contract priced per cluster. Book a discovery call for a quote. For other providers, see Kafka support providers.
Frequently asked questions
What is the difference between Kafka and NATS?
Kafka is a distributed log that stores every event on disk in partitioned topics for replay. NATS is a subject-based messaging system with publish-subscribe, request and reply, and queue groups; Core NATS stores nothing, and its JetStream layer adds persistent, replicated streams.
Kafka vs NATS JetStream: which is better?
JetStream is the better fit when you want persistence alongside NATS request and reply, multi-tenancy and edge deployments in one server. Kafka is the better fit for high-volume event pipelines with long retention, partitioned scale-out and a large connector and stream-processing ecosystem.
RabbitMQ vs NATS: when should I use each?
Use RabbitMQ for broker features: exchange-based routing, quorum queues, dead-lettering, priorities and AMQP, MQTT or STOMP clients. Use NATS for fast service-to-service messaging and request and reply, with JetStream when messages need to persist.
Kafka vs NATS vs RabbitMQ: how do the three compare?
Kafka is the log, RabbitMQ is the broker and NATS is the messaging fabric. Kafka keeps and replays events; RabbitMQ routes and tracks each message to a queue; NATS connects services by subject and adds persistence through JetStream.
Kafka vs NATS performance: which is faster?
Core NATS is designed for low latency because it stores nothing and waits for no acknowledgement. Kafka is designed for sustained throughput through batching and an append-only log. With persistence and replication switched on, both pay for durability. Benchmark your own message sizes and settings.
Does NATS guarantee message delivery?
Core NATS does not: it is at most once. JetStream gives at-least-once delivery through acknowledgements, and an exactly-once option through publisher message IDs and double acknowledgement.
Does OSSeva support NATS?
No. OSSeva supports Apache Kafka and RabbitMQ, among other messaging and data technologies, but not NATS.
Tags
Related articles
Kafka vs Redis: Streams, Pub/Sub, Queues and When to Use Each
October 8, 2026OperationsActiveMQ Classic vs Artemis: Which Broker to Run, Support Status and Performance
October 8, 2026OperationsApache Camel vs Spring Integration: Differences, When to Use Each and Support Windows
October 8, 2026Ready to get your open source under control?
Talk to an OSSeva engineer about CVE coverage, compliance, and migration support for your stack.