At-most-once, at-least-once and 'exactly once'

Distributed systems Senior Python 3.13+ PostgreSQL 17+ Reviewed By Best Latest Apps

Spot the bug

A consumer gets each message at least once. Which line makes a redelivery double-credit the account?

  1. processed: set[str] = set()
  2. balances = {"acc-1": 0}
  3. ​
  4. ​
  5. def handle(msg_id: str, account: str, amount: int) -> None:
  6. balances[account] += amount
  7. processed.add(msg_id)
  8. ​
  9. ​
  10. for msg in [("m1", "acc-1", 50), ("m1", "acc-1", 50)]:
  11. handle(*msg)
  12. print(balances)
Hint 1 of 1

Where is processed read?

Choose an answer, then open Show answer below to check it.

Show answer
  • Answer: line 6 balances[account] += amount

It adds before checking whether m1 was already processed. Check if msg_id in processed: return first, and in a real system record the id in the same transaction as the credit.

30-second answer

Not over an unreliable network: if an acknowledgement is lost, the sender can't tell whether the message arrived, so it either resends (at-least-once, possible duplicates) or doesn't (at-most-once, possible loss). What systems call exactly-once is effectively-once processing: at-least-once delivery plus idempotent handling or deduplication, or a transaction that commits the result and the consumer offset together.

Practise saying it · 35 s. No recording, just a timer

Is exactly-once possible?

Say your answer out loud, then check which of these points you covered:

  • Lost acks make delivery ambiguous
  • At-least-once or at-most-once
  • Effectively once = idempotent processing
  • Dedup ids in the same transaction

Deep dive

Kafka's exactly-once covers read-process-write inside Kafka (idempotent producer plus transactions); side effects outside Kafka still need idempotency.

Dedup needs a stable message id and a store of processed ids with a retention longer than the redelivery window.

Make the handler idempotent by design: upserts, 'set to' instead of 'add', unique constraints.

At-most-once is right for some data, like metrics where a gap is cheaper than a duplicate.

Common mistakes

  • Promising exactly-once delivery in a design doc.
  • Dedup by message id with a TTL shorter than the broker's redelivery window.
  • Assuming Kafka transactions make an email send exactly-once.

Senior take & follow-ups

Explain the lost-ack dilemma, then 'effectively once' as at-least-once plus idempotency.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you make 'charge card' idempotent?

    Show hint

    Pass an idempotency key to the payment provider.

  2. Where do you store processed ids?

    Show hint

    In the same database transaction as the effect.

Suggest a fix if something here is wrong or out of date.