The guarantee
At least once delivery means every message is processed one or more times, never zero. You get it by processing first and committing the offset only after the work succeeds. If the consumer crashes between processing and committing, the message is delivered again on restart.
The cost is duplicates
Because a crash after processing but before commit causes reprocessing, the consumer must tolerate duplicates. Side effects like sending an email or charging a card can fire twice unless the handler is idempotent.
Making it safe
- Idempotent writes: use the message key or an id so reapplying produces the same result.
- Dedup table: record processed message ids and skip ones already seen.
- Upserts: write with insert or replace semantics instead of blind appends.
Flow
Key idea
At least once never drops a message but may repeat it, so the consumer must be idempotent to make repeats harmless.