Real-World Guide: Redis Streams vs Apache Kafka vs Kafka Streams¶
1. Executive Summary & Core Concepts¶
In modern distributed systems, Event Streaming allows microservices to produce, process, and consume continuous flows of real-time data. However, engineers frequently face confusion when choosing between Redis Streams, Apache Kafka, and Kafka Streams.
What is a Stream?¶
A Stream is an append-only, ordered log of records (events). Unlike traditional Pub/Sub (where messages vanish after delivery) or simple Queues (where messages are deleted once processed by one consumer), a Stream retains messages in order, allowing multiple independent consumers to read at their own pace and replay history if needed.
[ Producer ] ──> Appends Event ──> [ APPEND-ONLY LOG ] ──> Consumer A (Offset 104)
──> Consumer B (Offset 80)
2. Redis Streams¶
What is Redis Streams?¶
Introduced in Redis 5.0, Redis Streams is an in-memory stream data structure stored as a Radix Tree inside RAM. It combines the speed of Redis with stream log semantics (IDs, consumer groups, pending entries, acknowledgement).
Internal Architecture & Mechanics¶
- Storage: In-Memory (RAM). Stream entries are compressed into
listpacknodes linked by a Radix tree. - IDs: Time-based 64-bit integer timestamp + sequence number (e.g.,
1723000000000-0). - Trimming (
MAXLEN): To prevent RAM exhaustion, streams must be capped (e.g.,XADD mystream MAXLEN ~ 5000 * field value). Old entries are pruned automatically. - Consumer Groups (
XREADGROUP): Allows a team of workers to share stream partition processing. - Pending Entries List (PEL): Tracks unacknowledged messages. If a worker crashes, another worker can reclaim pending messages via
XCLAIM.
When & Where to Use Redis Streams (Real-World Use Cases)¶
[!TIP] Use Redis Streams when you need sub-millisecond latency for transient or bounded real-time telemetry, and you already operate a Redis infrastructure.
- Live GPS / Telemetry Tracking (e.g., Uber/Lyft Driver Coordinates):
- Why: High-frequency location updates (100,000 updates/sec) that only matter while active. Older locations (> 10 minutes) can be pruned (
MAXLEN ~ 1000). - Latency Requirement:
< 1ms. - Real-Time Notification & In-App Activity Feeds:
- Why: User typing indicators, live viewer counters, transient alert feeds.
- Low-Latency Ephemeral Task Dispatching:
- Why: Distributing video rendering frames or web crawling jobs to a cluster of worker microservices with consumer groups (
XACK+XCLAIM). - Lightweight Event-Driven Architecture in Small-to-Medium Microservices:
- Why: You need consumer groups & message acknowledgments without the heavy ops burden of running a multi-node Kafka cluster.
When NOT to Use Redis Streams¶
- Long-term historical storage: RAM is too expensive for gigabytes/terabytes of event retention.
- Multi-day Event Replay: Once
XTRIM/MAXLENdrops old messages, they are lost forever. - Strict Financial Audit Logs: If Redis crashes before async RDB/AOF disk flush, unpersisted stream entries can be lost.
3. Apache Kafka¶
What is Apache Kafka?¶
Apache Kafka is a distributed, disk-backed commit log system designed for high-throughput, fault-tolerant event streaming across microservices and data platforms.
Internal Architecture & Mechanics¶
- Storage Engine: OS Page Cache + Sequential Disk I/O (Sequential disk writes are as fast as RAM random access).
- Topics & Partitions: A Topic is split into multiple Partitions across brokers. Partition key hashing guarantees strict ordering within a partition.
- Consumer Groups & Offsets: Consumers commit offsets (
__consumer_offsetstopic). Rebalancing occurs automatically if a consumer fails. - Zero-Copy Transfer: Uses
sendfile()syscall to transfer data directly from OS page cache to network socket without context switches. - Retention: Configurable log retention by time (e.g., 7 days, 30 days) or size (e.g., 500 GB), plus Log Compaction (retains only the latest state key).
When & Where to Use Apache Kafka (Real-World Use Cases)¶
[!IMPORTANT] Use Apache Kafka when you need a central, durable event bus for microservices, financial ledgers, CDC pipeline integration, and long-term event retention.
- Central Microservice Event Spine / Event-Driven Architecture:
- Why: Decouples dozens of microservices (Payment, Shipping, Inventory, Fraud, Analytics). Each service reads at its own speed without impacting others.
- Change Data Capture (CDC with Debezium):
- Why: Streaming Postgres/MySQL WAL logs directly into Kafka for syncing Elasticsearch, Neo4j, or Data Warehouses.
- Financial Ledger & Order Lifecycle Auditing:
- Why: Every order state change (
ORDER_CREATED,PAYMENT_APPROVED,SHIPPED) is saved durably on disk for compliance and replay. - Massive Log & Telemetry Ingestion (Data Lake Pipelines):
- Why: Ingesting millions of web clickstream events into Snowflake, BigQuery, or AWS S3 via Kafka Connect.
When NOT to Use Kafka¶
- Sub-millisecond latency requirement: Kafka latency is typically
2ms - 15ms(due to disk flush, network batching, replication ACKs). For< 1ms, Redis Streams is superior. - Simple, low-complexity applications: Running Kafka requires Zookeeper/KRaft brokers, partition sizing, topic administration, and consumer tuning.
4. Kafka Streams (Stream Processing Framework)¶
What is Kafka Streams?¶
While Apache Kafka is the transport & storage layer, Kafka Streams is a client library for building stateful, real-time stream processing applications.
Analogy: Kafka is the Database disk & log; Kafka Streams is the SQL query & analytics engine running continuous queries on the live stream.
Internal Architecture & Mechanics¶
- Stream-Table Duality:
KStream: Abstraction of an unbounded stream of records (Insert mode).KTable: Abstraction of a changelog stream representing current state (Upsert mode).- State Stores (Local RocksDB): Stateful operations (e.g., current account balance) are stored in embedded local RocksDB instances on the processing node, backed by a Kafka Changelog Topic.
- Time Windows:
- Tumbling Window: Non-overlapping fixed time windows (e.g., 00:00-00:05, 00:05-00:10).
- Hopping Window: Overlapping fixed time windows (e.g., 5-min window sliding every 1 min).
- Session Window: Grouped by activity gaps.
- Exactly-Once Processing (EOS): Uses Kafka transactional API to guarantee atomic reads, state updates, and writes.
When & Where to Use Kafka Streams (Real-World Use Cases)¶
[!TIP] Use Kafka Streams when you need to transform, aggregate, join, or calculate real-time metrics on Kafka streams with stateful windows.
- Real-Time Fraud Detection:
- Why: Count transaction volume for
Account_Xover a sliding 5-minute window (KStream.groupByKey().windowedBy()). If count > 10, trigger a fraud alert stream. - Live E-Commerce Sales Aggregation by Category:
- Why: Aggregate order totals in tumbling 1-minute windows and publish state directly to a live dashboard.
- Stream-Stream & Stream-Table Joins:
- Why: Enriching raw
OrderEventstream withUserProfileKTable state in real-time before sending to notification service. - Dynamic Surge Pricing Engine (e.g., DoorDash/Uber):
- Why: Compute demand ratio vs available drivers in 2-minute hopping windows per geohash zone.
5. Master Comparison Matrix¶
| Feature / Dimension | Redis Streams | Apache Kafka | Kafka Streams |
|---|---|---|---|
| Category | In-Memory Data Structure | Distributed Messaging Engine | Stateful Stream Processing Library |
| Storage Location | RAM | Disk + OS Page Cache | Local Disk (RocksDB) + Kafka Changelog |
| End-to-End Latency | Sub-millisecond (< 1ms) | Low Millisecond (2ms - 15ms) | Low Millisecond (5ms - 25ms) |
| Throughput (per node) | ~100k - 500k ops/sec | ~100k - 1M+ msg/sec | High (parallelized by partition count) |
| Retention Policy | Capped by size (MAXLEN) / RAM |
Time-based (Days/Years) or Size-based | Inherent to underlying Kafka Topics |
| Historical Replay | Limited (pruned history is lost) | Full replay from Offset 0 | Full state rebuild from Changelog |
| Processing Semantics | At-least-once / At-most-once | At-least-once / Exactly-once (Transactional) | Exactly-Once Processing (EOS) |
| Partition Model | Single key sharding in Redis Cluster | Explicit Topic Partitions | Derived from Kafka Topic Partitions |
| Stateful Operations | Manual via Redis Hashes/Keys | None (Storage & transport only) | Native (Windows, Joins, Aggregations) |
| Operational Complexity | Low (Simple Redis instance/cluster) | Medium-High (Brokers, KRaft, Partitions) | Medium (Runs as Java/Python application) |
6. Architectural Decision Tree Flowchart¶
[ What is your Primary Need? ]
│
┌────────────────────────────┼────────────────────────────┐
▼ ▼ ▼
[ High Speed, Ephemeral ] [ Central Event Log & Bus ] [ Real-Time Stateful Analytics ]
[ Transient Data ] [ Multi-Day Retention ] [ Windowing, Stream Joins, EOS ]
│ │ │
▼ ▼ ▼
REDIS STREAMS APACHE KAFKA KAFKA STREAMS
(Live GPS, In-App Feeds, (Microservice Event Bus, (Fraud Detection, Surge Pricing,
Notification Queues) CDC, Financial Audit) Rolling Window Aggregations)
7. Real-World Architecture Example: Ride-Hailing Platform (Uber / Lyft Model)¶
In a ride-hailing system, all three tech stacks work together:
[ Driver App ] ──> Sends GPS location every 1 sec ──> [ REDIS STREAMS ] ──> Driver Match Engine (<1ms response)
│
Periodic Sync
│
▼
[ Rider App ] ──> Creates Ride Request ───────────> [ APACHE KAFKA ] ────> Payment Service (Durable Ledger)
│
▼
[ KAFKA STREAMS ] ────> Computes Surge Pricing per Zone (5-min Window)
- Redis Streams: Driver sends live coordinates every 1 second. High throughput, transient, trimmed at
MAXLEN 1000. Match engine reads location with< 1mslatency. - Apache Kafka: When rider confirms a booking, the
RideCreatedevent is written to Kafka. Retained for 30 days for payment processing, driver payouts, and receipt generation. - Kafka Streams: Reads
RideCreatedevents from Kafka and aggregates ride demand by city zone over a sliding 5-minute window to dynamically compute Surge Pricing multipliers.
8. Summary & Rule of Thumb¶
- Use Redis Streams if speed (
<1ms) and low operational complexity are top priority, and older events can be discarded. - Use Apache Kafka if durability, high-throughput across services, multi-day retention, and historical replayability are mandatory.
- Use Kafka Streams if you are already consuming from Kafka and need complex, stateful calculations (sliding windows, aggregations, joins, exactly-once guarantees) directly on the stream.