Eight Idempotency Patterns and a Four-Layer Defense That Killed Duplicate Payment Tickets
Duplicate charges and orders are a direct revenue leak and trust killer for any payment or e-commerce system. This guide gives a decision framework and battle-tested code to eliminate them, regardless of your stack.
Duplicate payments and orders happen because users double-click, networks retry, and MQ redelivers. The solution is idempotency: making any repeated request produce identical side effects. This guide frames idempotency as a four-layer defense: frontend grey-out, gateway interception, business state machine or CAS, and a database unique index as the final correctness guarantee. It also provides a selection table and decision flow for eight patterns, from DB unique index and Token to optimistic lock and idempotency table.
The core code includes a Lua script that atomically checks and reserves a Redis key, an @Idempotent annotation that wraps SET NX EX with parameter fingerprinting, and an MQ dedup table that sits in the same transaction as the business. It also covers pitfalls like check-then-act races, clock rollback in Snowflake, and when to release the placeholder key on failure. The author reports that implementing this stack reduced monthly duplicate-charge tickets to zero.
The distinction between idempotency, deduplication, and concurrency control is often muddled; separating them clarifies why locks alone can't stop duplicates.
The four-layer defense accepts that no single mechanism is perfect; the unique index is the only absolute guarantee, which is why it sits last.
Result replay is the often-missed part of true idempotency: f(f(x))=f(x) requires the return value to match, not just the side effects.
Releasing the placeholder on retryable failures is a deliberate trade-off between retry safety and user experience, and it only works because DB constraints back it up.