Retries are inevitable. Duplicate delivery is inevitable. Partial failure is inevitable.
If correctness depends on application memory, your system will eventually produce duplicate side effects.
Modern systems retry automatically:
Retries are not edge cases. They are normal operating conditions.
Reference: AWS – Timeouts, Retries and Backoff
Client → POST /charge
Server → Charge credit card
Server → Save record
Server → Response lost
Client → Retry POST /charge
The first charge succeeded. The response was lost.
The second charge is now a duplicate.
Nothing failed. The network behaved normally.
A distributed lock prevents concurrent execution. It does not prevent sequential duplication.
Request A processed at 10:00:00
Request B retried at 10:00:05
The lock is already released. The system executes again.
Concurrency control ≠ idempotency.
Most message brokers guarantee at-least-once delivery:
At-least-once means duplicates are expected.
Reference: Kafka Delivery Semantics
Suppose:
3,000 × 0.5% = 15 duplicate attempts per second
15 × 3600 = 54,000 duplicate attempts per hour
Even if only 1% become real duplicate side effects:
54,000 × 1% = 540 duplicated transactions
Under scale, tiny percentages become operational incidents.
The only reliable solution: make duplication impossible at the storage layer.
CREATE UNIQUE INDEX ux_payment_idempotency
ON payments(idempotency_key);
INSERT INTO payments (idempotency_key, amount)
VALUES (@key, @amount)
ON CONFLICT (idempotency_key)
DO NOTHING;
If the same request arrives twice, the database enforces correctness.
The application becomes stateless.
1. Idempotency Key Pattern
SELECT response_payload
FROM idempotency_records
WHERE key = @key;
2. Outbox Pattern
Persist event and state change in same transaction. Publish asynchronously.
Reference: Transactional Outbox Pattern
3. Exactly-Once Is Mostly Marketing
Exactly-once delivery requires distributed consensus. Most production systems simulate it using:
Reference: Martin Kleppmann on Distributed Systems Guarantees
Locks control concurrency. Retries increase duplication. Queues guarantee redelivery.
Only the database can enforce uniqueness.
Idempotency is not an application concern. It is a data integrity constraint.