Every guide to message queues is secretly a throughput benchmark. It ranks systems by how many millions of messages per second they can push, because that is the number that fits in a headline and the workload most people historically had: firehoses of telemetry, clickstreams, logs — high-volume, low-consequence, individually disposable data where losing a sampled event costs nothing.

Agent systems invert almost every term in that sentence. The traffic that matters in an agent platform is low-volume and high-consequence: a planner deciding to call a tool, the tool returning a result, a human approving a risky action, a state transition from "waiting" to "executing." You do not have millions of these per second. You have a few per agent per minute, and each one is a fact you may need to answer for later. Optimizing that backbone for peak throughput is solving the wrong problem.

So before comparing the three obvious candidates, change the question. Not "how fast does it go," but "can I replay the log?" — because for agents, replay is what buys you recovery, deterministic debugging, and an audit trail of every tool call.

The three, by their actual shape#

A distributed event-streaming platform built around a partitioned, replicated commit log
★ 33kJavaapache/kafka

Kafka is a commit log first and a message queue second. Messages append to partitions; ordering is guaranteed within a partition, not across a topic. Consumers track their position by offset, the log is retained on a time or size policy, and that combination is the whole point — any consumer can rewind to any offset and replay. Delivery is at-least-once by default, exactly-once via idempotent producers and transactions.

Two 2025 changes matter. Kafka 4.0 (March 18, 2025) removed ZooKeeper entirely: KRaft, Kafka's own Raft metadata quorum, is now the only mode, which finally deletes the second cluster you used to babysit. And KIP-932 "share groups" are adding genuine queue semantics — per-message acknowledgement, redelivery, unordered processing — in early access in 4.0 and preview in 4.1, which is exactly the work-queue shape multi-agent fan-out wants. Kafka has the highest ceiling here and, even post-ZooKeeper, the heaviest footprint: a JVM broker cluster you operate.

High-performance cloud- and edge-native messaging; JetStream adds persistence, replay, and flow control

NATS with JetStream is the one built as if someone had read the agent requirements first. JetStream captures messages published to subjects into streams (memory or disk, 1–5 replicas) and exposes consumers as replayable views — you can replay instantly, at original rate, from a timestamp, or from a sequence number. Delivery is at-least-once, with exactly-once available through message dedup and a double-ack. The two features that earn it a place: it is a single Go binary with no external dependencies (the project treats third-party deps as a non-goal), so the ops cost rounds to zero; and it has per-subscription sliding-window flow control baked into the protocol. That backpressure is not a luxury when a single agent step can trigger a slow, expensive tool call and you need the planner not to bury the executors. (For why bounded backpressure beats unbounded queues in agent loops, see backpressure for AI agents.)

In-memory data-structure server whose Streams type is an append-only log with consumer groups
★ 75kCredis/redis

Redis Streams is the pragmatist's answer: an append-only log data type living inside a server a great many teams already run. XADD appends an entry with a time-ordered <ms>-<seq> ID (strict ordering for free), XREADGROUP reads through a consumer group so each message goes to exactly one member, XACK acknowledges, and unacked messages sit in a Pending Entries List you can reclaim with XCLAIM/XAUTOCLAIM after a crash. That is at-least-once delivery with a recovery story, and if Redis is already in your stack the marginal infrastructure cost is zero. The catch is durability: Redis persistence and Cluster are weaker by default than a replicated Kafka or JetStream log. One more footnote that may matter to your legal team — Redis 8 (GA May 1, 2025) is now tri-licensed under RSALv2, SSPLv1, and AGPLv3; the BSD-licensed lineage continues as the AWS/Google/Oracle-backed Valkey fork, which speaks the same Streams commands.

How to actually choose#

Stop ranking them by messages per second; for an agent backbone you will never be throughput-bound before you are correctness-bound. Ask three questions instead.

Can it replay? All three can — Kafka by offset, JetStream by sequence or timestamp, Redis Streams by ID range — which is precisely why you should reach for one of them and not raw pub/sub (Core NATS at-most-once, Redis Pub/Sub). Replay is how you recover a crashed run, re-drive a bad trajectory to debug it, and reconstruct the tool-call audit trail that compliance is starting to ask for.

Does it push back? JetStream's built-in flow control is the cleanest fit when slow consumers (tool executors) sit behind a fast producer (the planner). Kafka and Redis make backpressure your problem to engineer.

What are you willing to operate? If you already run Redis and want a durable log this afternoon, Redis Streams is the path of least resistance. If you want durability plus backpressure with almost no operational surface, NATS JetStream is the sweet spot. If you have — or will soon have — the scale and the team to run a JVM cluster, Kafka's ceiling is the highest, and post-4.0 it is finally one cluster instead of two.

The fan-out pattern is the same across all three: a consumer group of worker agents pulling tool-call work, per-key ordering preserved, explicit acks so a dead agent's in-flight task is redelivered rather than lost. That is the shape multi-agent orchestration actually needs. Pick the system whose default posture matches how much you want to operate — and once you have a durable event spine, the next decision is whether to run the long-lived work on it directly or hand it to a durable-execution engine: Temporal vs Inngest vs Restate, and how to trigger an agent at all.