hebel. today · 12 November 202667 / 74

Technology · Software Architecture Patterns

Payment systems prevent double charges with idempotency and atomic outboxes

Payment systems face failure modes that standard services avoid, specifically the ambiguity of a successful request with a lost response or a crash between a database write and an event publish. When a client…

Payment systems face failure modes that standard services avoid, specifically the ambiguity of a successful request with a lost response or a crash between a database write and an event publish (Arslan Ahmad from System Design Nuggets). When a client times out and retries a payment, or a message broker redelivers a 'PaymentCompleted' event, naive implementations often charge the user twice or decrement inventory multiple times. To guarantee that a charge occurs exactly once, engineers implement idempotency keys, which allow the payment service to recognize and ignore duplicate requests for the same order. Deduplication logic further ensures that repeated message deliveries do not trigger secondary effects in downstream services.

The transactional outbox pattern solves the dual-write problem by wrapping the database update and the event publication in a single atomic operation, ensuring that one never succeeds without the other. Arslan Ahmad explains that these three patterns form the correctness foundation of production financial infrastructure, as no finite message exchange can guarantee consensus in unreliable networks. While API gateways handle authentication and rate limiting, and load balancers distribute traffic across healthy instances, these specific patterns manage the integrity of the transaction state itself (Nikki Siapno from Level Up Coding System Design Newsletter).

Try today · 45 min

Add an idempotency key column to your payment database table and implement a check-before-process filter in your API handler.

Check for the existence of the key in your database before executing the charge logic.

You need

  • Database migration script
  • Unique constraint on the idempotency key column

Steps

  1. Add a column named 'idempotency_key' to your orders or payments table.
  2. Apply a unique index to this column to prevent race conditions.
  3. Modify your API endpoint to accept the key from the client header.
  4. Query the database for the key at the start of the request.
  5. Return the previous result if the key exists.
  6. Proceed with the transaction if the key is new.

One email instead of your newsletter pile.

Forward the newsletters you already get (a Gmail filter does it) and tell Hebel your goals. Every morning it reads them with 20,000 others and sends one short email, with one small thing to do today. Fewer emails, not more. Free during beta.

Start my paper →
LinkedIn X

Sources

  1. Nikki Siapno, Level Up Coding System Design Newsletter on hebel. → ✎ Written by a personThis article distinguishes between API gateway responsibilities like authentication and load balancer tasks like health checking and traffic distribution.

  2. Arslan Ahmad, System Design Nuggets on hebel. → ✎ Written by a personThis guide details three specific patterns—idempotency keys, deduplication, and the transactional outbox—required to prevent double charges in distributed systems.

More in Technology

Sorting data tiers to prevent AI leaks

Automating file maintenance with agents versus manual rules

Developers use comparison pages to judge AI-generated UI

Gemini Robotics 2.5 hits 96% success in Mercedes-Benz pilot

Automated bug-hunting resets patch volume

Guatemala pivots from necessity to fintech-led growth

Software Architecture Patterns yesterday

Application-level resilience versus infrastructure-sidecar control

Sign in to Hebel first

Likes, your collection and done Hebel need an account. We email you a six digit code; no password.