Nurvex logonurvex.ai
Book a call
Blogs
Blog/Engineering/Building Idempotent APIs: A Practical Guide
Engineering

Building Idempotent APIs: A Practical Guide

Every API that accepts a payment or triggers an automation will eventually receive the same request twice. Idempotency is what keeps that safe.

Every API that accepts a payment, sends a message, or triggers an automation will eventually receive the same request twice — a retried request, a flaky network, a client that doesn't know if the first attempt succeeded. Idempotency is what keeps that from becoming a double charge or a duplicate order.

The idempotency key is the whole pattern

The client generates a unique key per logical operation and sends it with the request. The server checks whether it has already processed that key; if so, it returns the original result instead of doing the work again.

idempotency.py
def handle_request(key, payload):
    existing = store.get(key)
    if existing:
        return existing.result

    result = process(payload)
    store.set(key, result, ttl_hours=48)
    return result

The subtlety most implementations miss is scoping: the key needs to be scoped to the operation and the request payload, not just a bare identifier, or a client can accidentally replay a different request under an old key.

Store idempotency keys with a TTL, not forever — an unbounded key store is a slow leak that shows up as a mystery cost six months later.

Idempotency doesn't mean "safe to retry blindly"

Idempotent doesn't mean free — it means safe. A retried request should still hit the network and the datastore; it just shouldn't cause a second side effect. Teams that conflate the two end up building retry logic that hammers a struggling downstream service instead of protecting it.

Done well, idempotency is invisible. Nobody notices it working. They only notice when it's missing, and by then it's usually a customer-facing incident.

Get the next one in your inbox

One good idea a week, no spam.