Skip to Content
ComparisonsOverview

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 curl as 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.

CapabilitytopicsRedis StreamsKafkaNATS JetStreamCloud queues
Durability modelPer-topic class: ephemeral (resident-only) / memory / disk (group commit) / fsync (fsync-gated ack), single node, no replicationGlobal RDB / AOF (appendfsync always|everysec|no); async replicasPer-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 signalExplicit in-band tombstone [gap_from, gap_to] at read timeSilent (MAXLEN / MINID / XDEL trim quietly)Silent (offset reset per auto.offset.reset)Silent (infer from stream-seq jumps)Silent (no per-consumer gap signal)
OrderingPer-topic monotonic $seq (u64)Per-stream entry IDs <ms>-<seq>Per-partition offsets onlyPer-stream sequencePer-shard (Kinesis) / ordering keys (Pub/Sub) / FIFO group (SQS)
Delivery & ackAt-least-once by default; router exactly_once suppresses duplicate derived dest appends by stable key; cursor-advance ack for logs, lease ack/nack for queuesAt-least-once via consumer-group PEL (XACK / XCLAIM)At-least-once default; exactly-once via txns + read_committedAt-least-once; AckExplicit / AckAll / AckNoneAt-least-once; SQS FIFO / Pub/Sub exactly-once options
Fan-outRouters + multiplexed SSE (one connection, many topics)Pub/Sub (at-most-once) or multiple consumer groupsMultiple consumer groups read independentlyMultiple consumers + subject wildcardsSNS push fan-out to heterogeneous endpoints
QueuesNative lease queues (claim / ack / nack / extend) + dead-letter moveConsumer groups (PEL); XAUTOCLAIM reclaimGroups cap at partition count; KIP-932 share groups are a previewPull consumers + AckWait redelivery; MaxDeliver advisory (DIY DLQ)First-class (SQS visibility timeout + native DLQ)
DeletionTargeted, permanent deletes by seq range and/or tag (exact/prefix)XDEL by ID; trim by MAXLEN / MINIDNo point delete; log compaction drops superseded keysStream purge / per-subject limitsAck = delete; no replay (SQS), seek/replay (Kinesis, Pub/Sub)
DeploymentOne static binary, one data dir, HTTP/JSON; no SDKSingle binary; Redis Cluster for shardingMulti-node JVM cluster (KRaft)Single binary; clusters / superclusters / leaf nodes for HAFully managed, nothing to run
ScaleVertical only (~1M events/s aggregate target on one NVMe-backed machine)Vertical + Redis Cluster sharding; RAM-bounded historyHorizontal (brokers / partitions); 15M+ msg/s on big clustersHorizontal (clusters / leaf nodes)Elastic, far beyond one machine
ProtocolPlain HTTP/JSON + SSE; curl is a clientRESP (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

Last updated on