A minimal Kafka-like message broker written in Go.
Single-node, durable storage with partitioned topics, offset-based consumption, persistent consumer offsets, and auto-polling consumers supporting independent consumer groups.
- Partitioned Topics with append-only logs
- Log Segmentation with automatic rotation (max 10 messages per segment)
- Durable Message Storage persisted to disk
- Offset-based Consumption with efficient segment indexing
- Persistent Consumer Offsets tracked per consumer group
- Concurrent Producers and Consumers via goroutines
- Thread-safe Operations with fine-grained locking (sync.RWMutex)
go run cmd/broker/main.goThe broker listens on:
localhost:9092
Messages are persisted to the storage/ directory.
go run cmd/producer/main.goThe producer connects to the broker and waits for JSON input.
Example request:
{
"type": "produce",
"topic": "orders",
"partition": 0,
"message": "order-123"
}Response:
ack offset 0
go run cmd/consumer/main.go --topic orders --partition 0 --group group1 --poll-interval 1sThe --group flag identifies the consumer group.
Each group tracks its own offset independently, allowing multiple consumers to process the same topic without interfering with each other.
The consumer:
- Polls the broker every 1 second
- Fetches messages from the last committed offset
- Persists offsets to disk after processing
- Supports independent consumer groups
For interactive topic selection (without flags):
go run cmd/consumer/main.go- TCP server built using Go's
netpackage - Goroutine per client connection
- Request routing for produce and fetch operations
- Append-only log split into segments for scalability
- Each segment stores up to 10 messages
- Segments persist to disk as
{topic}-{partition}-{baseOffset}.log - On startup, broker reloads all segments from disk
- Offsets are derived from segment base offset + message index
Example file structure:
storage/
orders-0-0.log (partition 0, messages 0-9)
orders-0-10.log (partition 0, messages 10-19)
orders-1-0.log (partition 1, messages 0-9)
sync.RWMutexensures thread-safe partition access- Multiple readers allowed concurrently
- Writes are serialized per partition
- JSON-based request/response format
- Simple and human-readable for development clarity
Offsets are persisted to storage/{consumer-group}-{topic}-{partition}.offset:
- Each consumer group tracks progress independently
- Offsets saved to disk after processing messages
- On restart, consumers resume from last committed offset
- Enables fault tolerance and crash recovery
go run cmd/broker/main.gogo run cmd/producer/main.goThen enter:
{
"type": "produce",
"topic": "test",
"partition": 0,
"message": "hello"
}{
"type": "produce",
"topic": "test",
"partition": 0,
"message": "world"
}go run cmd/consumer/main.go --topic test --partition 0 --group group1You should see the messages appear via auto-polling and the consumer saves its offset to: storage/group1-test-0.offset
Stop the consumer and run it again
go run cmd/consumer/main.go --topic test --partition 0 --group group1The consumer resumes from the last saved offset, avoiding reprocessing old messages.
Stop the consumer and run it again
go run cmd/consumer/main.go --topic test --partition 0 --group group2This consumer starts from offset 0 because it has its own independent offset file: storage/analytics-test-0.offset
- Immediate disk writes prioritise durability over peak throughput
- In-memory indexing keeps fetch operations efficient
- JSON protocol favours simplicity over network efficiency
- Single-node design focuses on log semantics before distributed complexity
- Multi-node deployment
- Leader-follower model
- Quorum-based acknowledgements
- Partition rebalancing across consumers
- Broker-managed offset storage
- Heartbeats and group coordination
- Buffered disk writes
- Reduced syscall overhead
- Throughput optimisation
- Structured logging
- Metrics exposure
- Profiling and benchmarking