KafkaIQ

1.1 End-to-End Message Flow & Core Architecture

Module Overview

Goal: Show the complete internal path of a record through Kafka's machinery.

What You'll Learn:

  • Producer → Broker → Partition → Log → Replica → Consumer flow
  • Request handling pipeline inside brokers
  • Network layer and I/O thread architecture
  • Data plane vs control plane separation
  • High-level internal architecture

What's NOT Covered Here:

  • Producer configuration details (covered in Producer modules)
  • Consumer configuration details (covered in Consumer modules)
  • Performance tuning (covered in Operations modules)
  • Specific topic design (covered in Operations modules)

Key Insight: Understanding the full internal message journey reveals why Kafka behaves the way it does. This is "inside the machine" knowledge.


1. The Complete Message Journey

High-Level Flow

PRODUCER → BROKER → PARTITION → LOG → REPLICAS → CONSUMER

Step-by-step:

1. Producer constructs ProducerRecord
   └─ Serializes key and value to bytes

2. Producer sends batch to broker (leader for target partition)
   └─ Network request with ProduceRequest

3. Broker receives request on network thread
   └─ Validates and queues for processing

4. I/O thread writes to partition log
   └─ Appends to active log segment on disk

5. Followers fetch data from leader
   └─ Replication to maintain durability

6. High watermark advances
   └─ Data becomes visible to consumers

7. Consumer fetches data
   └─ FetchRequest to broker

8. Consumer receives records
   └─ Deserializes and processes

Visual Architecture

┌─────────────────────────────────────────────────────────────┐
│                      PRODUCER                               │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐            │
│  │ Serializer │→ │ Partitioner│→ │RecordBatch │            │
│  └────────────┘  └────────────┘  └────────────┘            │
└─────────────────────────┬───────────────────────────────────┘
                          │ ProduceRequest
                          ↓
┌─────────────────────────────────────────────────────────────┐
│                   KAFKA BROKER                              │
│                                                              │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              NETWORK LAYER                            │  │
│  │  ┌──────────────┐  ┌──────────────┐                  │  │
│  │  │ Acceptor     │→ │ Processor    │→ Request Queue   │  │
│  │  │ (port 9092)  │  │ (N threads)  │                  │  │
│  │  └──────────────┘  └──────────────┘                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                          ↓                                   │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              REQUEST HANDLER POOL                     │  │
│  │  ┌──────────────┐  ┌──────────────┐                  │  │
│  │  │ I/O Thread 1 │  │ I/O Thread N │                  │  │
│  │  └──────────────┘  └──────────────┘                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                          ↓                                   │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              LOG MANAGER                              │  │
│  │  ┌──────────────┐  ┌──────────────┐                  │  │
│  │  │ Partition 0  │  │ Partition 1  │  ...             │  │
│  │  │ (Log)        │  │ (Log)        │                  │  │
│  │  └──────────────┘  └──────────────┘                  │  │
│  └──────────────────────────────────────────────────────┘  │
│                          ↓                                   │
│  ┌──────────────────────────────────────────────────────┐  │
│  │              REPLICATION                              │  │
│  │  ┌──────────────┐  ┌──────────────┐                  │  │
│  │  │ Leader       │→ │ Follower     │                  │  │
│  │  │ (this broker)│  │ (other broker│                  │  │
│  │  └──────────────┘  └──────────────┘                  │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────┬───────────────────────────────────┘
                          │ FetchRequest
                          ↓
┌─────────────────────────────────────────────────────────────┐
│                      CONSUMER                               │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐            │
│  │  Fetcher   │→ │Deserializer│→ │ Application│            │
│  └────────────┘  └────────────┘  └────────────┘            │
└─────────────────────────────────────────────────────────────┘

2. Broker Internal Architecture

Three Core Subsystems

1. NETWORK LAYER
   └─ Handles TCP connections and protocol parsing

2. REQUEST PROCESSING LAYER
   └─ Executes business logic (produce, fetch, metadata)

3. STORAGE LAYER
   └─ Manages partition logs on disk

Network Layer Details

COMPONENTS:

Acceptor Thread:
├─ Binds to configured port (default: 9092)
├─ Accepts new client connections
└─ Assigns connections to processor threads

Processor Threads (num.network.threads):
├─ Read requests from sockets
├─ Parse request protocol
├─ Queue requests for processing
└─ Send responses back to clients

Request Queue:
├─ Bounded queue between network and I/O threads
└─ Backpressure mechanism if handlers are slow

Flow:

Client Connection
     ↓
Acceptor Thread (1 thread)
     ↓
Processor Thread (3-8 threads)
     ↓ (enqueue)
Request Queue (in-memory)
     ↓ (dequeue)
I/O Handler Thread (8-16 threads)

Request Processing Layer

HANDLER THREADS (num.io.threads):

Responsibilities:
├─ Dequeue requests from request queue
├─ Execute request logic:
│   ├─ ProduceRequest → write to log
│   ├─ FetchRequest → read from log
│   ├─ MetadataRequest → return cluster metadata
│   └─ OffsetCommitRequest → update consumer offsets
├─ Interact with log manager
└─ Enqueue response for network layer

Thread Pool Size:
└─ Typically 8-16 threads
└─ More threads = higher throughput (up to a point)

Storage Layer (Log Manager)

LOG MANAGER:

Manages all partition logs for broker:
├─ One log per partition replica hosted on this broker
├─ Each log = sequence of segment files
└─ Coordinates:
    ├─ Writes (appends)
    ├─ Reads (fetch)
    ├─ Log rolling (new segments)
    ├─ Log cleanup (retention/compaction)
    └─ Index management

Partition Log:
└─ Append-only structure
└─ Segments rotated based on size or time
└─ Indexes for fast offset lookup

3. Producer Request Handling

ProduceRequest Internal Flow

STEP-BY-STEP:

1. ProduceRequest arrives at broker
   └─ Contains: topic, partition, records, acks level

2. Network thread parses request
   └─ Validates protocol
   └─ Enqueues for I/O thread

3. I/O thread dequeues request
   └─ Authorization check (if security enabled)
   └─ Partition validation

4. Request routed to Log Manager
   └─ Log.append(records)

5. Log Manager writes to active segment
   ├─ Assigns offsets sequentially
   ├─ Writes to OS page cache
   └─ fsync (if required by config)

6. If acks=all, wait for ISR replicas
   └─ Followers fetch data
   └─ Leader tracks acknowledgments

7. Response sent back to producer
   └─ Success: offset of first record
   └─ Error: error code

Offset Assignment

INTERNAL MECHANISM:

Each partition maintains:
└─ Log End Offset (LEO): Next offset to be written

When new records arrive:
1. Current LEO: 1000
2. Batch has 10 records
3. Assign offsets: 1000, 1001, ..., 1009
4. Append to log
5. New LEO: 1010

Offsets are:
├─ Sequential (per partition)
├─ Immutable (never change)
├─ Unique (within partition)
└─ Dense (no gaps in normal operation)

Acknowledgment Levels (Internal Behavior)

acks=0 (No acknowledgment):
└─ Broker accepts request
└─ Immediately returns success
└─ No guarantee data is written

acks=1 (Leader acknowledgment):
└─ Broker writes to leader's log
└─ Returns success after leader write
└─ No guarantee of replication

acks=all (ISR acknowledgment):
└─ Broker writes to leader's log
└─ Waits for all ISR replicas to fetch
└─ Returns success after ISR acknowledgment
└─ Highest durability guarantee

4. Consumer Fetch Request Handling

FetchRequest Internal Flow

STEP-BY-STEP:

1. FetchRequest arrives at broker
   └─ Contains: topic, partition, offset, max bytes

2. Network thread parses request
   └─ Enqueues for I/O thread

3. I/O thread dequeues request
   └─ Validates: Is this broker the leader for partition?

4. Check offset vs High Watermark
   ├─ If offset > HW: Wait or return empty
   └─ Only committed data is visible

5. Log Manager reads from log
   ├─ Uses offset index to find segment
   ├─ Reads from segment file
   └─ Applies max.bytes limit

6. Zero-copy optimization (if possible)
   └─ sendfile() system call
   └─ Data goes directly from disk to network
   └─ No intermediate buffer copies

7. Response sent back to consumer
   └─ Records + metadata (HW, next offset)

High Watermark Visibility

KEY CONCEPT:

High Watermark (HW):
└─ Last offset fully replicated to all ISR replicas
└─ Only records up to HW are visible to consumers

Example:
├─ Leader LEO: 1010
├─ Follower 1 LEO: 1008
├─ Follower 2 LEO: 1009
└─ High Watermark: 1008 (minimum of ISR LEOs)

Consumer fetch at offset 1005:
└─ Can read up to offset 1007
└─ Records 1008, 1009, 1010 are NOT visible yet
└─ (Not yet replicated to all ISR members)

Zero-Copy Transfer

TRADITIONAL COPY:

Disk → OS Buffer → Kafka Buffer → Socket Buffer → Network
└─ 4 copies, 2 context switches

ZERO-COPY (sendfile):

Disk → OS Buffer → Network
└─ 1 copy, 1 context switch
└─ 10x faster for large sequential reads

Enabled when:
├─ SSL/TLS is NOT enabled (encrypts in user space)
└─ Data is not compressed differently than stored

5. Data Plane vs Control Plane

Separation of Concerns

DATA PLANE:
└─ Handles client requests (produce, fetch)
└─ High throughput, low latency critical
└─ Bulk of broker traffic

CONTROL PLANE:
└─ Handles cluster coordination
└─ Leader elections, metadata updates
└─ Lower throughput, consistency critical

Data Plane Operations

CLIENT-FACING REQUESTS:

ProduceRequest:
└─ Write records to partition logs

FetchRequest:
└─ Read records from partition logs (consumers & followers)

OffsetFetch/OffsetCommit:
└─ Consumer offset management

MetadataRequest:
└─ Topic/partition/broker discovery

ListOffsets:
└─ Find offsets by timestamp

Control Plane Operations

CLUSTER COORDINATION:

Controller → Broker:
├─ LeaderAndIsrRequest (partition leadership changes)
├─ StopReplicaRequest (remove replica)
└─ UpdateMetadataRequest (cluster state sync)

Broker → Controller:
├─ BrokerHeartbeat (liveness)
└─ AlterPartitionRequest (ISR changes)

Broker → ZooKeeper/KRaft:
└─ Metadata reads/writes

Why Separation Matters

BENEFITS:

1. Resource Isolation:
   └─ Control plane issues don't block data plane

2. Different Performance Profiles:
   ├─ Data plane: Throughput optimized
   └─ Control plane: Consistency optimized

3. Different Failure Modes:
   ├─ Data plane: Can continue if metadata is stale
   └─ Control plane: Needs strong consistency

6. Request Pipeline Architecture

Threading Model

KAFKA BROKER THREADS:

1. Acceptor (1 thread):
   └─ Accept new connections

2. Processor (num.network.threads):
   └─ Read/write from sockets
   └─ Default: 3-8 threads

3. Request Handler (num.io.threads):
   └─ Process requests (produce, fetch, etc.)
   └─ Default: 8-16 threads

4. Log Cleaner (log.cleaner.threads):
   └─ Compact logs
   └─ Default: 1 thread

5. Replication Fetcher (num.replica.fetchers):
   └─ Fetch from leaders (follower side)
   └─ Default: 1 thread

6. Background (background.threads):
   └─ Miscellaneous tasks
   └─ Default: 10 threads

Request Queue Mechanics

BOUNDED QUEUE:

RequestQueue (size: queued.max.requests):
├─ Producers: Processor threads enqueue
├─ Consumers: I/O threads dequeue
└─ Backpressure: If full, network threads block

Flow control:
├─ Full queue → producers experience increased latency
├─ Empty queue → I/O threads idle
└─ Balanced: Queue depth 10-50% of max

Request Priority (Optional)

SOME KAFKA VERSIONS SUPPORT PRIORITY:

High Priority:
└─ Controller requests (LeaderAndIsr, etc.)
└─ Ensures control plane works even under load

Normal Priority:
└─ Client requests (produce, fetch)

Implementation:
└─ Separate queues or priority queue

7. Partition Routing

How Producers Find the Right Broker

METADATA DISCOVERY:

1. Producer connects to any broker (bootstrap server)
   └─ MetadataRequest

2. Broker returns cluster metadata:
   ├─ All brokers (id, host, port)
   ├─ All topics and partitions
   └─ Leader for each partition

3. Producer caches metadata
   └─ Knows which broker hosts leader for partition X

4. Producer sends ProduceRequest to correct broker
   └─ Directly to leader (no proxy)

5. Metadata refresh on errors
   └─ NOT_LEADER_FOR_PARTITION error triggers refresh

Leader-Only Writes

CRITICAL RULE:

All writes go to the partition leader:
├─ Leader assigns offsets
├─ Leader appends to log
└─ Leader coordinates replication

Followers are read-only (internally):
└─ Followers only fetch from leader
└─ Followers do NOT accept client writes

Why?
└─ Ensures single source of truth
└─ Simplifies consistency model

8. Replication Flow (High-Level)

Follower Fetch Loop

FOLLOWER BEHAVIOR:

While (true) {
    1. Send FetchRequest to leader
       └─ Includes current offset

    2. Leader responds with new records
       └─ If any available

    3. Follower appends to local log
       └─ Same offsets as leader

    4. Follower sends next FetchRequest
       └─ With updated offset
}

Key Points:
├─ Follower pulls (not pushed)
├─ Fetch includes current offset (for leader tracking)
└─ Leader tracks follower progress

ISR Membership

IN-SYNC REPLICA SET (ISR):

Leader maintains ISR set:
├─ All replicas that are "caught up"
├─ "Caught up" = within replica.lag.time.max.ms

If follower falls behind:
├─ Leader removes from ISR
└─ ISR shrinks

When follower catches up:
├─ Leader adds back to ISR
└─ ISR expands

ISR impacts:
└─ acks=all waits for all ISR members
└─ Smaller ISR = faster acks (but less durability)

9. Broker Startup Sequence

Internal Initialization

BROKER STARTUP PHASES:

1. Load Configuration
   └─ server.properties
   └─ Validate settings

2. Initialize Log Manager
   ├─ Scan log.dirs
   ├─ Load partition logs
   ├─ Recover unclean shutdown
   └─ Build offset indexes

3. Register with ZooKeeper/KRaft
   ├─ Broker ID registration
   ├─ Create ephemeral node (ZK)
   └─ Join controller quorum (KRaft)

4. Fetch Metadata from Controller
   └─ Partition assignments
   └─ Leader/follower roles

5. Start Network Layer
   └─ Bind to listeners
   └─ Start acceptor and processor threads

6. Start Replication Threads
   └─ For partitions where broker is follower

7. Mark Broker as Alive
   └─ Ready to serve traffic

10. Key Internal Invariants

Core Guarantees

KAFKA INTERNAL RULES:

1. Offsets are sequential per partition
   └─ No gaps (in normal operation)

2. Leader assigns offsets
   └─ Followers replicate exact same offsets

3. High watermark never decreases
   └─ (except on unclean leader election)

4. Data up to HW is immutable
   └─ Safe to read by consumers

5. Leader election preserves committed data
   └─ New leader must have all HW data

6. Replicas diverge → truncation happens
   └─ Follower truncates to leader's HW

11. Why This Architecture?

Design Decisions

APPEND-ONLY LOG:
└─ Sequential writes are fast (even on HDD)
└─ Simplifies replication (just copy log)
└─ Immutability simplifies consistency

PULL-BASED CONSUMPTION:
└─ Consumer controls pace (backpressure)
└─ Broker doesn't track consumer state (stateless)
└─ Multiple consumers at different speeds

LEADER-BASED REPLICATION:
└─ Single writer (leader) per partition
└─ No distributed consensus per write
└─ Fast writes, eventually consistent reads

ZERO-COPY:
└─ Leverage OS page cache
└─ Avoid user-space copies
└─ Kernel handles disk → network

12. Performance Characteristics

Why Kafka is Fast

1. SEQUENTIAL DISK I/O:
   └─ Append-only log = sequential writes
   └─ Sequential reads for consumers
   └─ Modern disks excel at sequential I/O

2. BATCH PROCESSING:
   ├─ Producers batch records
   ├─ Brokers write batches
   └─ Consumers fetch batches
   └─ Amortizes overhead

3. ZERO-COPY:
   └─ sendfile() system call
   └─ No user-space buffer copies

4. PAGE CACHE:
   └─ OS caches recently written data
   └─ Reads often served from memory
   └─ No need for large JVM heap

5. COMPRESSION:
   └─ Stored compressed on disk
   └─ Transferred compressed over network
   └─ Reduces I/O and bandwidth

13. Key Takeaways

You've learned:

✅ Complete message journey from producer to consumer through broker internals
✅ Network layer handles connections and protocol parsing
✅ I/O threads execute request logic (produce, fetch)
✅ Log Manager appends to partition logs on disk
✅ Offsets are assigned sequentially by the partition leader
✅ High Watermark determines consumer visibility
✅ Replication is pull-based (followers fetch from leader)
✅ Data plane vs control plane separate client traffic from coordination
✅ Zero-copy optimization for fast data transfer
✅ Sequential I/O is the foundation of Kafka's performance


14. Architecture Checklist

BROKER INTERNAL COMPONENTS:

☑ Network Layer (Acceptor, Processors)
☑ Request Queue (bounded, backpressure)
☑ I/O Threads (request handlers)
☑ Log Manager (partition logs)
☑ Replication Manager (ISR tracking)
☑ Controller Client (leadership updates)

REQUEST FLOW:

☑ Producer → Network → Queue → I/O → Log → Disk
☑ Consumer ← Network ← I/O ← Log ← Disk (or cache)
☑ Follower → Fetch → Leader → Replicate → Local Log

PERFORMANCE OPTIMIZATIONS:

☑ Sequential disk I/O
☑ Batching (producer, broker, consumer)
☑ Zero-copy (sendfile)
☑ OS page cache utilization
☑ Compression

Summary

Kafka's internal architecture prioritizes:

Core Design =
├─ Append-only log (simple, fast, durable)
├─ Leader-based replication (no consensus per write)
├─ Pull-based consumption (consumer controls pace)
├─ Zero-copy transfers (leverage kernel)
└─ Sequential I/O (disk-friendly)

Request Pipeline =
├─ Network threads (parse protocol)
├─ Request queue (buffer, backpressure)
├─ I/O threads (execute logic)
└─ Log Manager (manage storage)

Performance =
├─ Batching everywhere
├─ OS page cache as primary cache
├─ Compression in flight and at rest
└─ Minimal data copies

Remember: Kafka's architecture makes trade-offs favoring throughput, simplicity, and durability. Understanding these internals explains why Kafka behaves the way it does under load, failure, and scale.

Next up: Module 2.1 — Topic & Partition Internals — Deep dive into partition structure and offset mechanics.