Skip to content

In-Memory Payment Message Queue

Published 3 October 2026

Coding — In-Memory Payment Message Queue

The queue exposed an interface similar to:

interface PaymentMessageQueue {
    void submit(PaymentMessage message);
    PaymentMessage receive();
    void ack(String messageId);
}

The basic behavior was:

  • submit(message) adds a payment message to the queue.
  • receive() returns the next available message.
  • Once received, that message should become temporarily invisible to other consumers.
  • ack(messageId) permanently removes a successfully processed message.
  • If the message is not acknowledged before its visibility timeout expires, it should become available for delivery again.

Follow-Up — Concurrent Consumers

The first major concurrency question was what happens when two consumers call receive() at nearly the same time. The interviewer specifically pushed on whether both consumers could accidentally obtain the same payment message and how the queue should prevent that race.

My initial implementation choice exposed an issue here, which led into a deeper discussion of how ownership should transfer when a message moves from the pending state into an in-flight state.