Urgent.News

What's breaking now, across thousands of outlets.

Tech

Making POST Requests Safe to Retry with Idempotency Keys

A practical guide to duplicate execution, request fingerprints, concurrency, and safe retries. A request timeout does not mean the operation failed. Sometimes the server has already completed the operation, but the response never reaches the client. Consider: POST /orders/order-123/pay with: { "amount" : 500000 } The timeline may look like this: Client -> POST /pay Server -> payment succeeds…

Duplicate execution of requests can lead to problems even if the HTTP request is retried. The goal is to ensure that one logical operation results in one effective side effect, regardless of how many times the request is delivered. To achieve this, an idempotency key is introduced by the client. This key remains the same for the same logical operation, even if retries occur.

When a request comes in, the system checks the idempotency key. If it's a new key, the operation is processed and the result is stored. If the key already exists, the system replays the stored response without executing the side effect again. This prevents duplicate side effects from occurring.

The traditional "check-then-act" method fails because if the idempotency key doesn't exist, two concurrent requests might both process the payment, leading to a race condition. To solve this, the uniqueness decision needs to be atomic. In a relational database, this can be achieved by enforcing a unique constraint on the idempotency key.

An idempotency key must represent exactly one logical operation. The same key with the same payload can be safely replayed, but the same key with a different payload should not be accepted. The lab uses a request fingerprint based on SHA-256 to ensure that same key + same fingerprint results in safe replay, while same key + different fingerprint results in a 409 conflict.

The safe flow has two key states: PROCESSING and COMPLETED. When a second request arrives, the system returns a 409 error, indicating that the operation is already in progress. If the operation is already finished, the system loads the stored response and replays it.

Idempotency is not a database transaction, as it protects a logical operation across multiple execution attempts, rather than ensuring atomicity within a single execution. A database transaction provides atomicity inside one execution, while idempotency protects the operation across multiple attempts. For example, if a payment provider successfully processes a payment and the local commit fails, the rollback does not undo the external charge. In such cases, the backend should reuse a stable key for that external request too.

In the lab implementation, the unsafe version directly charges the payment without any additional checks. The safe version, on the other hand, validates the key, calculates the fingerprint, reserves the operation, marks it as PROCESSING, executes the payment, stores the result, and marks it as COMPLETED. The storage implementation uses a map with a sync.RWMutex to simulate atomic uniqueness without introducing a real database. Both versions can be run and compared using the provided testing commands.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Pannonico 0.6: how a personal side project is becoming a professional tool

A few weeks ago I wrote about Pannonico, the static site generator I've been building in Go. At that point I mostly focused on its architecture and performance: Pannonico handles pages, templates and…

  • Pannonico 0.6.0 released with improved editor tooling and language server.
  • Pannonico syntax respected, not interpreted as template in CommonMark code blocks.
  • Pannonico startup time around 22-33 ms, faster than Hugo and Eleventy.

Browser video background removal held up on a talking head and fell apart in a street crowd

![ ]( https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/bSwapping the background on a video in a browser tab, with the video never leaving your machine, is the kind of thing I try the…

  • Compatible model used for testing with three public domain clips
  • Issues with fast-moving hands and overlapping figures in street performance
  • Gradient background visible through lower half of people in front

We Built an Arcade for Our Own Game Engine

Or: how I spent three months using the platform we built at Evolved Tech, noticing what was broken, and refusing to stop At Evolved Tech , my co-founder Kehinde Owolabi built the core: epic.js , our…

  • Co-founder Kehinde Owolabi created epic.js, a lightweight 2D game engine.
  • Desire developed arcade platform and leaderboard system for showcasing games.
  • Usernames for game creators implemented, solving broken links issue.

More from Tuesday 15 September →