DEV Community

Vishal Aggarwal
Vishal Aggarwal

Posted on • Originally published at javalld.com

Java LLD: Designing a Kafka-Like Message Queue for Machine Coding Interviews

Java LLD: Designing a Kafka-Like Message Queue for Machine Coding Interviews

Designing a high-performance message queue is a frequent requirement in senior-level machine coding rounds. It tests your ability to balance thread safety with decoupled architecture while managing stateful consumer progress.

The mistake most candidates make

  • Using a standard java.util.Queue that removes elements upon polling, which prevents multiple consumer groups from reading the same data.
  • Coupling the Producer directly to the Consumer logic, violating the Pub-Sub principle and making the system brittle to scale.
  • Failing to implement independent offset management, leading to data loss or duplicate processing when one consumer lags.

The right approach

  • Core mental model: An immutable, append-only log where messages are persisted per topic, allowing consumers to track their own progress independently.
  • Key entities: Topic, Message, Subscriber, ConsumerGroup, OffsetManager.
  • Why it wins: It enables "replayability" and allows multiple heterogeneous systems to consume the same stream at different speeds without interference.

Implementation Insight: The Thread-Safe Log

public class Topic {
    private final List<Message> messages = new ArrayList<>();
    private final ReentrantLock lock = new ReentrantLock();

    public void addMessage(Message message) {
        lock.lock();
        try {
            messages.add(message);
        } finally {
            lock.unlock();
        }
    }

    public List<Message> getMessagesFrom(int offset) {
        return (offset >= messages.size()) ? List.of() : messages.subList(offset, messages.size());
    }
}
Enter fullscreen mode Exit fullscreen mode

Key takeaways

  • Decouple producers and consumers by using an append-only log structure instead of a destructive queue.
  • Use ReentrantLock to ensure atomic appends to the message log in a multi-threaded producer environment.
  • Manage consumer state via independent offsets, allowing each ConsumerGroup to process messages at its own pace.

Full working implementation with execution trace available at https://javalld.com/problems/message-queue

Top comments (0)