01

Requirements & scope

Problem Statement & Requirements

Design a distributed message queue system that decouples producers from consumers, enables asynchronous processing, guarantees message delivery, and scales to handle millions of messages per second — similar to Apache Kafka, AWS SQS, or RabbitMQ.

Functional Requirements

  • Producers publish messages to named topics
  • Consumers subscribe to topics and receive messages in order
  • Support consumer groups — multiple consumers sharing the load of a topic, each message delivered to exactly one consumer in the group
  • Messages are persisted on disk, not lost on broker failure
  • Support at-least-once, at-most-once, and exactly-once delivery semantics (configurable)
  • Consumers can replay messages from a specific offset (time-travel)
  • Support message retention by time (e.g., 7 days) or size (e.g., 1 TB per topic)
  • Ordering guarantees within a partition (not across partitions)
  • Dead letter queue (DLQ) for messages that fail processing after N retries

Non-Functional Requirements

  • High throughput — handle millions of messages/second per cluster
  • Low latency — end-to-end publish-to-consume in < 10 ms (p99) for real-time use cases
  • Durability — zero message loss once acknowledged by the broker
  • High availability — survive broker failures, rack failures, even AZ failures
  • Horizontal scalability — add brokers to increase throughput linearly
  • Fault tolerance — automatic leader election and partition rebalancing on failure

Out of Scope

  • Complex message routing (fanout, topic exchanges like RabbitMQ — simplified to topic-partition model)
  • Message transformation / stream processing (that's Kafka Streams / Flink territory)
  • Multi-tenancy and authentication (simplify for interview)
02

Scale estimations

Scale Estimations

Traffic

MetricValue
Messages produced / second1M (peak: 3M)
Average message size1 KB
Messages consumed / second3M (each message consumed by ~3 consumer groups on average)
Number of topics10,000
Number of partitions (total)100,000
Number of producers50,000
Number of consumer groups5,000

Storage

MetricValue
Data ingested / second1M × 1 KB = 1 GB/s
Data ingested / day1 GB/s × 86,400 = ~86 TB/day
Retention period7 days
Raw storage (7 days)86 TB × 7 = ~600 TB
Replication factor3
Total storage (with replication)600 TB × 3 = ~1.8 PB
Storage per broker (50 brokers)1.8 PB / 50 = ~36 TB per broker

Bandwidth

MetricValue
Incoming (produce)1 GB/s
Outgoing (consume, 3 consumer groups avg)3 GB/s
Replication traffic (2 replicas × 1 GB/s)2 GB/s
Total network throughput~6 GB/s cluster-wide
Per broker (50 brokers)~120 MB/s per broker

Hardware Estimate (per broker)

ComponentSpec
CPU16-24 cores (mostly I/O bound)
RAM64-128 GB (OS page cache is critical)
Disk8× 4 TB NVMe SSDs in JBOD (32 TB usable)
Network10 Gbps NIC (25 Gbps preferred)
Brokers in cluster50-100
03

Layered architecture

Phase 1 of 4 · Client & edge

Start with the entry points

First, define who uses the system and where requests enter. This is the boundary of the design, not yet a complete request path.

Producers
Choose a partition key that captures the ordering boundary your application actually needs.
Discovery
Locate each partition leader and refresh metadata when leadership changes.
Architecture after phase 1. Includes Producers, Discovery. Producers connects to Discovery.
Phase 1 — Start with Producers, Discovery.SVGSVGEditable diagramEditable diagram

This first layer defines the system boundary. The next chapters add application logic and data dependencies. After examining the request paths and tradeoffs, we will add operational safeguards and bring the complete architecture together.

04

API & contracts

Phase 2 of 4 · Application & compute

Add the application logic

Keep the entry points and add the services that do the work. Give each service a clear responsibility before defining its contracts. Storage and background dependencies come next.

Leader brokers
Append batches sequentially and acknowledge according to the selected durability policy.
Consumers
Assign each partition to one active group member while allowing independent subscriber groups.
Architecture after phase 2. Includes Producers, Discovery, Leader brokers, Consumers. Producers connects to Discovery. Discovery connects to Leader brokers. Consumers connects to Leader brokers.
Phase 2 — Added Leader brokers, Consumers. Earlier layers remain in place.SVGSVGEditable diagramEditable diagram

API Design

Producer API

EXAMPLE
POST /api/v1/topics/{topic_name}/messages
Content-Type: application/json

Request:
{
  "key": "user-123",                    // partition key (optional — null = round-robin)
  "value": "base64-encoded-payload",     // the message body
  "headers": {                           // optional metadata
    "correlation-id": "req-abc",
    "content-type": "application/json"
  },
  "partition": 3,                        // optional — explicit partition override
  "timestamp": 1712150400000             // optional — defaults to broker time
}

Response (202 Accepted):
{
  "topic": "user-events",
  "partition": 3,
  "offset": 847291,
  "timestamp": 1712150400000
}

Consumer API

EXAMPLE
GET /api/v1/topics/{topic_name}/messages?group_id=analytics-pipeline
    &max_messages=500
    &timeout_ms=5000

Response (200 OK):
{
  "messages": [
    {
      "key": "user-123",
      "value": "base64-encoded-payload",
      "headers": {"correlation-id": "req-abc"},
      "partition": 3,
      "offset": 847291,
      "timestamp": 1712150400000
    },
    ...
  ]
}

Commit Offset (Acknowledge)

EXAMPLE
POST /api/v1/topics/{topic_name}/offsets
Content-Type: application/json

Request:
{
  "group_id": "analytics-pipeline",
  "offsets": [
    {"partition": 0, "offset": 12345},
    {"partition": 3, "offset": 847292}
  ]
}

Response: 204 No Content

Admin API

EXAMPLE
POST   /api/v1/topics                     — Create topic (name, partitions, replication_factor, retention)
DELETE /api/v1/topics/{topic_name}        — Delete topic
PUT    /api/v1/topics/{topic_name}/config — Update retention, compaction, etc.
GET    /api/v1/topics/{topic_name}/info   — Topic metadata (partitions, leaders, ISR)
POST   /api/v1/topics/{topic_name}/partitions — Add partitions (cannot decrease)

SDK-Level API (Internal Binary Protocol — High Performance)

EXAMPLE
// Producer (batch-oriented)
producer.send(topic, key, value, headers) → Future<RecordMetadata>
producer.flush()                          → blocks until all buffered messages sent

// Consumer (poll-based)
consumer.subscribe(topics, group_id)
records = consumer.poll(timeout_ms)       → batch of ConsumerRecords
consumer.commitSync(offsets)              → block until offsets durably stored
consumer.commitAsync(offsets, callback)   → fire-and-forget with callback
consumer.seek(partition, offset)          → rewind/fast-forward to specific offset
05

Data model

Phase 3 of 4 · Data & async work

Connect data and background work

The services now need their dependencies: durable state, fast lookups, or work that continues outside a request. Separate these responsibilities rather than treating every component as a database.

Replica brokers
Replicate logs and restrict safe leader election to replicas with the required committed history.
Offset store
Track committed consumer progress; application effects need idempotency or transactions on replay.
Cluster controller
Coordinate partition placement and leader changes using a quorum-backed metadata plane.
Architecture after phase 3. Includes Producers, Discovery, Leader brokers, Consumers, Replica brokers, Offset store, Cluster controller. Producers connects to Discovery. Discovery connects to Leader brokers. Leader brokers connects to Replica brokers. Consumers connects to Leader brokers. Consumers connects to Offset store. Cluster controller connects to Leader brokers.
Phase 3 — Added Replica brokers, Offset store, Cluster controller. Earlier layers remain in place.SVGSVGEditable diagramEditable diagram

Data Model

Core Abstractions

Core Abstractions
Core AbstractionsSVGSVGEditable diagramEditable diagram

Message Record (On-Disk Format)

Message Record (On-Disk Format)
Message Record (On-Disk Format)SVGSVGEditable diagramEditable diagram

Log Segment (On-Disk Storage Unit)

EXAMPLE
Partition Directory: /data/user-events-0/

  00000000000000000000.log      ← active segment (append-only)
  00000000000000000000.index    ← sparse offset → file position index
  00000000000000000000.timeindex← timestamp → offset index
  00000000000065536000.log      ← rolled segment (immutable)
  00000000000065536000.index
  00000000000065536000.timeindex

Segment rolls when:
  - Size exceeds segment.bytes (default 1 GB)
  - Time exceeds segment.ms (default 7 days)
  - Index file is full

Offset Storage

Offset Storage
Offset StorageSVGSVGEditable diagramEditable diagram

Core Design Decisions — The Storage Engine

The most critical design decision in a message queue is how messages are stored and retrieved. This determines throughput, latency, durability, and operational complexity.

Option 1: Append-Only Log on Disk (Kafka's Approach)

Option 1: Append-Only Log on Disk (Kafka's Approach)
Option 1: Append-Only Log on Disk (Kafka's Approach)SVGSVGEditable diagramEditable diagram

Why sequential I/O matters:

I/O PatternHDDSSD
Sequential write100-200 MB/s500-3000 MB/s
Random write0.1-1 MB/s50-200 MB/s
Sequential read100-200 MB/s500-3000 MB/s
Random read0.1-1 MB/s50-200 MB/s

Sequential I/O is 100-1000× faster than random I/O. By only appending, Kafka achieves disk throughput that rivals network throughput.

Zero-copy transfer (sendfile):

EXAMPLE
Traditional path:                    Zero-copy path:
Disk → Kernel buffer                 Disk → Kernel buffer
Kernel buffer → User buffer             ↓  (sendfile syscall)
User buffer → Socket buffer          Kernel buffer → NIC buffer
Socket buffer → NIC buffer

4 copies, 4 context switches         2 copies, 2 context switches
~60% of CPU on data copies           ~0% CPU on data copies
ProsCons
Extremely high throughput (millions msg/sec)No per-message deletion (retention-based only)
Sequential I/O leverages OS page cacheMessages are immutable once written
Zero-copy transfers to consumersConsumer must track own offset
Simple — append + read, no complex data structuresOrdering only within a partition

Option 2: In-Memory Queue with WAL (RabbitMQ-style)

Option 2: In-Memory Queue with WAL (RabbitMQ-style)
Option 2: In-Memory Queue with WAL (RabbitMQ-style)SVGSVGEditable diagramEditable diagram
ProsCons
Very low latency (microsecond for in-memory)Memory-limited — can't buffer large backlogs
Per-message ACK and deletionComplex — memory management, overflow to disk
Flexible routing (exchanges, bindings)Lower throughput at scale vs log-based
Push-based deliveryNo message replay after consumption

Option 3: Database-Backed Queue (SQS-style)

Option 3: Database-Backed Queue (SQS-style)
Option 3: Database-Backed Queue (SQS-style)SVGSVGEditable diagramEditable diagram
ProsCons
Fully managed (SQS), no operationsLower throughput (1000s msg/s vs millions)
At-least-once with visibility timeoutNo ordering guarantees (SQS standard)
Per-message deletionHigher latency (database round-trips)
Simple operational modelNo replay capability

Recommendation

Use Option 1 (Append-Only Log) for a high-throughput, scalable message queue:

  • Sequential I/O + zero-copy = unmatched throughput
  • Persistent storage = unlimited retention and replay
  • Simple broker logic = operational simplicity
  • Consumer offset tracking = flexible consumption patterns
06

Core design decisions

Choose the ordering boundary before choosing the partition count. Events for one business key can share a partition, but separate partitions progress independently. A consumer acknowledgement says how far processing has advanced under its contract; it does not make an external database write and an offset commit automatically atomic.

07

Request flows

Detailed Flow Diagrams

Produce Flow

Produce Flow
Produce FlowWide diagram — scroll horizontally.SVGSVGEditable diagramEditable diagram

Consume Flow (Pull-Based)

Consume Flow (Pull-Based)
Consume Flow (Pull-Based)Wide diagram — scroll horizontally.SVGSVGEditable diagramEditable diagram

Consumer Rebalance Flow

Consumer Rebalance Flow
Consumer Rebalance FlowWide diagram — scroll horizontally.SVGSVGEditable diagramEditable diagram
08

Performance & caching

Log Compaction (Bonus Deep Dive)

Log Compaction (Bonus Deep Dive)
Log Compaction (Bonus Deep Dive)SVGSVGEditable diagramEditable diagram
09

Advanced design

Replication & Consistency

ISR (In-Sync Replicas)

ISR (In-Sync Replicas)
ISR (In-Sync Replicas)SVGSVGEditable diagramEditable diagram

Acks Configuration & Durability Tradeoffs

acks SettingBehaviorDurabilityLatencyThroughput
acks=0Producer doesn't wait for any ACKLowest — fire and forget~0.5 msHighest
acks=1Wait for leader to write to local logMedium — lost if leader dies before replication~2-5 msHigh
acks=allWait for all ISR replicas to writeHighest — survives any single broker failure~5-15 msLower

Recommendation: acks=all with min.insync.replicas=2 for production:

  • Tolerates 1 broker failure without data loss
  • Blocks produces if ISR shrinks below 2 (prevents single-replica writes)

Leader Election

Leader Election
Leader ElectionSVGSVGEditable diagramEditable diagram

Partitioning Strategy

How Messages Are Routed to Partitions

How Messages Are Routed to Partitions
How Messages Are Routed to PartitionsSVGSVGEditable diagramEditable diagram

Partition Count Selection

EXAMPLE
Target throughput: 1 GB/s

Single partition throughput:
  - Producer: ~10-50 MB/s per partition
  - Consumer: ~20-100 MB/s per partition (consumer is usually faster)
  - Bottleneck is typically producer side

Calculation:
  Required partitions = Target throughput / Per-partition throughput
                      = 1 GB/s / 30 MB/s (conservative)
                      = ~34 partitions per topic (round up to 36-48)

Rule of thumb:
  - Start with max(expected_throughput / 30MB, num_consumers_in_largest_group)
  - Can always ADD partitions later (cannot remove)
  - More partitions = more parallelism BUT more open file handles,
    longer leader election, more memory for consumer offset tracking

Partition-to-Consumer Assignment Strategies

StrategyHow It WorksProsCons
RangeAssign consecutive partitions to consumers (P0-P2→C1, P3-P5→C2)Preserves key locality for co-partitioned topicsUneven if partition count not divisible by consumers
Round-RobinDistribute partitions one by one (P0→C1, P1→C2, P2→C1...)Even distributionBreaks key co-partitioning
StickyLike round-robin but minimizes reassignment during rebalanceFewer partition movements on rebalanceSlightly more complex
Cooperative StickyIncremental rebalance — only moves partitions that need movingNear-zero downtime rebalancingRequires multiple rebalance rounds

Recommendation: Cooperative Sticky Assignor — minimizes stop-the-world rebalancing.

10

Edge cases

Handling Edge Cases

Consumer Lag & Backpressure

EXAMPLE
Problem: Consumer is slower than producer → unbounded lag
  
Monitoring:
  consumer_lag = latest_offset(partition) - committed_offset(consumer_group, partition)
  
Mitigations:
  1. Scale out consumers (up to # of partitions)
  2. Increase consumer fetch size (fetch.max.bytes)
  3. Tune consumer processing (batch DB writes, parallelize)
  4. Add partitions to topic (+ proportional consumers)
  5. Alert when lag exceeds threshold (e.g., > 100K messages)

Exactly-Once Semantics (EOS)

Exactly-Once Semantics (EOS)
Exactly-Once Semantics (EOS)SVGSVGEditable diagramEditable diagram

Dead Letter Queue (DLQ)

Dead Letter Queue (DLQ)
Dead Letter Queue (DLQ)SVGSVGEditable diagramEditable diagram

Message Ordering Across Partitions

EXAMPLE
Problem: User actions must be ordered, but topic has 12 partitions

Solution: Use the entity ID as the partition key
  - key = "user-123" → hash("user-123") % 12 = partition 7
  - ALL events for user-123 go to partition 7
  - Within partition 7, ordering is guaranteed

Caveat: If you add partitions, hash changes → key mapping shifts
  - Mitigate: Don't add partitions to topics where key ordering matters
  - Or: use a custom partitioner with a stable mapping table

Large Messages

Large Messages
Large MessagesSVGSVGEditable diagramEditable diagram
11

Tradeoffs

Tradeoffs & Design Decisions Summary

DecisionOption AOption BChosenWhy
Storage EngineAppend-only log (Kafka)In-memory + WAL (RabbitMQ)Append-only logSequential I/O = highest throughput; unlimited retention; replay capability
Delivery ModelPull (consumer polls)Push (broker pushes)PullConsumer controls pace; no backpressure on broker; natural batching
Metadata StoreZooKeeper (external)KRaft (self-managed)KRaftRemoves external dependency; simpler operations; better scaling (>200K partitions)
Ordering ScopeGlobal orderingPer-partition orderingPer-partitionGlobal ordering = 1 partition = no parallelism; per-partition is the right balance
Consumer OffsetBroker tracks (auto)Consumer commits (manual)Manual commitApplication controls exactly-once semantics; no re-processing on crash
Acksacks=1 (leader only)acks=all (full ISR)acks=allData loss is unacceptable for most use cases; latency cost is acceptable (5-15 ms)
ReplicationSynchronousAsynchronousSync for ISRAsync loses data on leader failure; sync ISR guarantees committed = durable
RebalancingStop-the-worldCooperative incrementalCooperativeStop-the-world pauses ALL consumers during rebalance; cooperative only moves affected partitions
CompactionDelete old segmentsLog compaction (keep latest per key)BothDelete for event streams; compaction for changelog/state topics
Wire ProtocolHTTP/RESTCustom binary (TCP)BinaryLower overhead, better batching, connection multiplexing; REST for admin only
12

Reliability & fault tolerance

Phase 4 of 4 · Operations & resilience

Add operational safeguards

With the request paths and tradeoffs established, add the controls that help detect trouble and keep the system operating. The final diagram retains every layer introduced so far.

Queue telemetry
Watch consumer lag, replica health, and retention capacity before slowdowns become outages.
Architecture after phase 4. Includes Producers, Discovery, Leader brokers, Consumers, Replica brokers, Offset store, Cluster controller, Queue telemetry. Producers connects to Discovery. Discovery connects to Leader brokers. Leader brokers connects to Replica brokers. Consumers connects to Leader brokers. Consumers connects to Offset store. Cluster controller connects to Leader brokers. Leader brokers connects to Queue telemetry.
Phase 4 — Added Queue telemetry. Earlier layers remain in place.SVGSVGEditable diagramEditable diagram

Reliability & Fault Tolerance

Single Points of Failure & Mitigations

Single Points of Failure & Mitigations
Single Points of Failure & MitigationsSVGSVGEditable diagramEditable diagram

Graceful Degradation

EXAMPLE
Scenario: Broker goes down (1 of 50)

  1. Controller detects missing heartbeat (18s timeout)
  2. For each partition where dead broker was leader:
     → Elect new leader from ISR
     → Update metadata, notify clients
  3. For each partition where dead broker was follower:
     → Remove from ISR
     → Continue with remaining ISR
  4. When broker returns:
     → Fetches missed data from current leaders
     → Rejoins ISR after catching up
     → Preferred leader election restores original topology

Impact: ~5-30s of unavailability for affected partitions
         Other partitions continue unaffected
         Zero data loss (acks=all with min.insync.replicas=2)

Data Durability Guarantees

Data Durability Guarantees
Data Durability GuaranteesSVGSVGEditable diagramEditable diagram
13

Production architecture

High-Level Architecture

High-Level Architecture
High-Level ArchitectureSVGSVGEditable diagramEditable diagram

Component Breakdown

Component Breakdown
Component BreakdownSVGSVGEditable diagramEditable diagram

Key: P0-L = Partition 0 Leader, P0-F = Partition 0 Follower

Full System Architecture (Production-Grade)

Full System Architecture (Production-Grade)
Full System Architecture (Production-Grade)Wide diagram — scroll horizontally.SVGSVGEditable diagramEditable diagram
14

Further exploration

Let a consumer complete a database write and crash before committing its offset. On restart, the message is delivered again. Design the deduplication or transactional boundary that makes this safe, then check what changes if the side effect is a third-party API rather than your own database.

15

Interview playbook

Interview Tips

  1. Start with the append-only log insight — This is the foundational design decision. Explain why sequential I/O and zero-copy make disk-based queues faster than in-memory alternatives at scale.

  2. Draw the partition model early — Topics → Partitions → Segments. This shows you understand the parallelism model. Emphasize: ordering is per-partition, not per-topic.

  3. Discuss the acks tradeoff in depth — acks=0 vs acks=1 vs acks=all. Connect it to ISR and min.insync.replicas. This is a nuanced durability vs latency discussion interviewers love.

  4. Explain consumer groups and rebalancing — How partitions are assigned, what triggers a rebalance, why cooperative sticky is preferred over stop-the-world. Mention the "consumers ≤ partitions" constraint.

  5. Address exactly-once semantics — Most candidates only know at-least-once. Explaining idempotent producers (PID + sequence number) and transactions sets you apart.

  6. Mention KRaft over ZooKeeper — Shows you know the modern architecture. ZooKeeper was a bottleneck at >200K partitions. KRaft uses Raft consensus built into the brokers themselves.

  7. Discuss operational concerns — Partition count selection, when to add partitions (and why you can't remove them), retention policies, monitoring consumer lag, dealing with hot partitions.

  8. Claim-check pattern for large messages — Shows pragmatism. Don't just increase max.message.bytes — explain the S3 reference pattern.

  9. Compare with alternatives when asked — Kafka (high throughput, log-based) vs RabbitMQ (flexible routing, push-based) vs SQS (managed, simple). Each has its sweet spot.

  10. End with scale numbers — "A single Kafka cluster with 50 brokers can handle 1M+ messages/sec, store petabytes with 7-day retention, and serve hundreds of consumer groups simultaneously."