Comparisons
topics is a single-binary, single-machine event engine: an append-only log over plain HTTP and JSON, with per-topic durability classes, lease queues, server-side routers, and multiplexed SSE. These pages compare it honestly against the systems people reach for instead — Redis Streams, Apache Kafka, NATS JetStream, and managed cloud queues — and are explicit about where each of those wins.
How to read these comparisons
Every page below follows the same rule: no strawmen. Each alternative is excellent at what it was built for, and each comparison includes a “where it wins” section that is true, not grudging. topics is not a Kafka replacement and does not pretend to be. It occupies a specific point in the design space, and the comparisons exist to help you find out whether that point fits your problem.
Positioning
topics makes one deliberate trade: it is a single machine. There is no replication, no failover, and no horizontal scale-out — one process on one NVMe-backed machine is both the durability domain and the failure domain. In exchange you get two things the distributed systems mostly do not offer:
- Operational simplicity. One static binary, one data directory, plain HTTP/JSON, and
curlas a complete client. No cluster to bootstrap, no quorum to babysit, no broker JVM, no SDK or binary wire protocol. You can run the whole product from a shell. - An explicit, in-band loss signal. When involuntary cap eviction or TTL expiry
destroys records below a reader’s cursor, the next read returns a tombstone with
the exact
[gap_from, gap_to]range — at HTTP 200, at delivery time. The four systems below all trim or age data out silently and leave gap detection to lag metrics or sequence-number jumps. topics treats “you missed data” as a first-class event.
On top of that single substrate, topics runs logs, lease queues, and fan-out together,
bridged by routers with node loop-prevention,
and offers per-topic durability classes (ephemeral / memory / disk / fsync) instead of one
server-wide persistence mode, plus targeted, permanent, point-in-time deletes by seq
range and/or tag.
The honest, recurring “alternative wins” axis is the same on every page: topics has no replication, no HA/failover, no horizontal scale-out, and has no transactions or end-to-end exactly-once processing. It is self-hosted with no native TLS (run it behind a reverse proxy). If you need any of those, the alternative is the right tool. See Durability for the single-node failure model.
Capability matrix
A high-level, deliberately blunt comparison. “Single node / no replication” is stated plainly for topics because it is the central trade. Each system has nuance the dedicated pages cover — this table is the 30-second version.
| Capability | topics | Redis Streams | Kafka | NATS JetStream | Cloud queues |
|---|---|---|---|---|---|
| Durability model | Per-topic class: ephemeral (resident-only) / memory / disk (group commit) / fsync (fsync-gated ack), single node, no replication | Global RDB / AOF (appendfsync always|everysec|no); async replicas | Per-partition log via replication (acks, min.insync.replicas) | Per-stream file / memory; optional RAFT replicas (1/3/5) | Managed, multi-AZ / regional replicated |
| Gap / loss signal | Explicit in-band tombstone [gap_from, gap_to] at read time | Silent (MAXLEN / MINID / XDEL trim quietly) | Silent (offset reset per auto.offset.reset) | Silent (infer from stream-seq jumps) | Silent (no per-consumer gap signal) |
| Ordering | Per-topic monotonic $seq (u64) | Per-stream entry IDs <ms>-<seq> | Per-partition offsets only | Per-stream sequence | Per-shard (Kinesis) / ordering keys (Pub/Sub) / FIFO group (SQS) |
| Delivery & ack | At-least-once by default; router exactly_once suppresses duplicate derived dest appends by stable key; cursor-advance ack for logs, lease ack/nack for queues | At-least-once via consumer-group PEL (XACK / XCLAIM) | At-least-once default; exactly-once via txns + read_committed | At-least-once; AckExplicit / AckAll / AckNone | At-least-once; SQS FIFO / Pub/Sub exactly-once options |
| Fan-out | Routers + multiplexed SSE (one connection, many topics) | Pub/Sub (at-most-once) or multiple consumer groups | Multiple consumer groups read independently | Multiple consumers + subject wildcards | SNS push fan-out to heterogeneous endpoints |
| Queues | Native lease queues (claim / ack / nack / extend) + dead-letter move | Consumer groups (PEL); XAUTOCLAIM reclaim | Groups cap at partition count; KIP-932 share groups are a preview | Pull consumers + AckWait redelivery; MaxDeliver advisory (DIY DLQ) | First-class (SQS visibility timeout + native DLQ) |
| Deletion | Targeted, permanent deletes by seq range and/or tag (exact/prefix) | XDEL by ID; trim by MAXLEN / MINID | No point delete; log compaction drops superseded keys | Stream purge / per-subject limits | Ack = delete; no replay (SQS), seek/replay (Kinesis, Pub/Sub) |
| Deployment | One static binary, one data dir, HTTP/JSON; no SDK | Single binary; Redis Cluster for sharding | Multi-node JVM cluster (KRaft) | Single binary; clusters / superclusters / leaf nodes for HA | Fully managed, nothing to run |
| Scale | Vertical only (~1M events/s aggregate target on one NVMe-backed machine) | Vertical + Redis Cluster sharding; RAM-bounded history | Horizontal (brokers / partitions); 15M+ msg/s on big clusters | Horizontal (clusters / leaf nodes) | Elastic, far beyond one machine |
| Protocol | Plain HTTP/JSON + SSE; curl is a client | RESP (vast client ecosystem) | Binary protocol + rich ecosystem (Connect, Streams, ksqlDB) | NATS protocol (+ native TLS/WS/MQTT) | Cloud SDK / HTTP APIs (IAM/KMS) |
The aggregate ~1M events/sec figure is a design target reached by batching and sharding across many topics and connections — a single HTTP origin tops out around 0.5M records/sec disk-class on one NVMe-backed machine. See Performance for measured numbers and how to frame them.
Dig into a specific system
In-memory speed and ecosystem vs durable history beyond RAM and explicit gap signals — plus where Redis Pub/Sub fits.
vs Redis StreamsReplicated horizontal scale and exactly-once vs one binary, HTTP/JSON, and the opposite meaning of “tombstone.”
vs Apache KafkaThe closest single-binary peer: subjects, RAFT replication, and accounts vs delivery-time tombstones and HTTP/JSON.
vs NATS JetStreamSQS / SNS / Kinesis / Pub/Sub: zero-ops managed HA vs self-hosted data locality and a never-silent loss signal.
vs Cloud Queues