Skip to content
Go back

Deep Dive: Building a Distributed Message Broker from Scratch

Table of contents

Open Table of contents

Why I Built a Distributed Message Broker from Scratch

Understanding how Apache Kafka works is one thing; actually building it is another. To truly grasp memory-mapped logs, sequential storage, offset management, and consensus, I decided to build a “Mini-Kafka” in Java from scratch.

This write-up breaks down the engineering design decisions I made, how my implementation maps to Kafka’s core components, and the lessons learned in low-level concurrency and systems storage.


1. The Storage Engine: The Heart of the Log

Original Kafka:

Kafka’s performance secret isn’t magic; it’s Sequential I/O. Instead of using complex B-trees (like MySQL) or Hash Maps (like Redis), Kafka uses a Distributed Partitioned Append-Only Log.

My Implementation: LogSegment.java & PartitionLog.java


2. Horizontal Scaling: Topics & Partitions

Original Kafka:

A Topic is a logical stream of data, but a Partition is the physical unit of scalability. Multiple partitions allow multiple brokers to share the load.

My Implementation: KafkaBroker.java


3. The Consumer Model: Offsets & Pull-based Protocol

Original Kafka:

Unlike RabbitMQ (which pushes data and tracks consumer state), Kafka consumers Pull data and track their own Offsets. This makes Kafka “stateless” from the broker’s perspective.

My Implementation: MiniKafkaConsumer.java


4. Producer Intelligence: Partitioning Strategies

Original Kafka:

The producer decides which partition a message goes to, not the broker.

My Implementation: MiniKafkaProducer.java


5. The Wire Protocol: Custom TCP

Original Kafka:

Kafka uses a optimized binary protocol over TCP to reduce the overhead of headers (like HTTP).

My Implementation: KafkaServer.java & KafkaCommand.java


6. Metadata Consensus: KRaft & Raft

Original Kafka:

Legacy Kafka used Zookeeper. Kafka 3.x+ uses KRaft—an internal Raft-based metadata log.

My Implementation: RaftNode.java

This was the most complex part to replicate. I built a simplified Raft Consensus Engine:


Core Engineering Takeaways

Building this broker highlighted several core systems engineering challenges:

  1. Thread Safety under Load: Managing concurrent client readers and writers on the same log files required careful locking and thread-safe collections.
  2. Crash-Safe Persistence: Making sure that write failures or sudden crashes don’t corrupt the offset state or log segment files.
  3. Consensus Protocols: Coding the state transitions (Follower, Candidate, Leader) of the Raft election algorithm and keeping term counts synchronized.
  4. Network Optimization: Reducing round-trips by implementing metadata caching on the producer side.

Why Kafka Wins

Building this broker made it clear why Kafka is so dominant. Its simplicity—the append-only log—is its core strength. By eliminating complex indexing on the broker and pushing offset state tracking entirely to the consumer, Kafka achieves a level of write throughput and simplicity that traditional brokers can’t match.

Project source code and implementation documentation can be found in this repository.


Share this post on:

Previous Post
Kubernetes Storage
Next Post
CIDR