← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Idempotency

general Intermediate
debt(d7/e5/b7/t5)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). The detection_hints state automated detection is 'no' and the only tool listed is semgrep, which can catch specific code patterns (INSERT without ON DUPLICATE KEY, payment processing without idempotency key) but only if custom rules are written — it won't catch the general design failure. Missing idempotency in webhook handlers or queue consumers is typically discovered at runtime when duplicates appear in production, not before.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes needing to design write operations to be safely repeatable using UPSERT, check-before-insert, or idempotency keys. This isn't a one-line swap — it requires changing the data model (adding idempotency key columns), updating API handlers, modifying database queries, and possibly reworking retry logic across a component. It doesn't typically reach full architectural rework, but it touches multiple layers within a service.

b7 Burden Structural debt — long-term weight of choosing wrong

Closest to 'strong gravitational pull' (b7). The term applies_to web, api, and queue-worker contexts — essentially all write-path interactions in a distributed system. Every future feature involving payments, webhooks, or queue consumers must be designed with idempotency in mind. The common_mistakes list shows it affects payments, message queues, auto-increment IDs, and DELETE behavior — it shapes how every write operation is designed, making it a persistent and broad architectural constraint.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field explicitly states the trap: developers believe GET is automatically safe and POST is never idempotent, but application-level idempotency is a separate design concern independent of HTTP method semantics. This is a well-documented gotcha — most developers learn it after their first duplicate-charge or duplicate-record incident — but it contradicts a partially correct mental model (HTTP methods DO have idempotency semantics) making it a notable, not catastrophic, trap.

About DEBT scoring →

Also Known As

idempotent operation idempotent API safe retry

TL;DR

An operation is idempotent if performing it multiple times produces the same result as performing it once — essential for safe retries.

Explanation

Idempotency is critical in distributed systems where network failures cause uncertainty about whether a request succeeded. HTTP GET, PUT, and DELETE are idempotent by definition; POST is not. For non-idempotent operations (payment processing, email sending), implement idempotency keys: the client generates a unique key per operation and includes it in the request; the server stores the key and result, returning the cached result for duplicate requests. In PHP APIs, store idempotency keys in Redis or a database with a TTL and return 200 with the original response body for duplicates.

Common Misconception

GET requests are automatically idempotent but POST requests never are. HTTP GET and DELETE are defined as idempotent; POST is not by spec. But application-level idempotency is a design choice — a POST that creates a resource can be made idempotent via an idempotency key that deduplicates retried requests.

Why It Matters

An idempotent operation produces the same result whether called once or many times — essential for safe retries in distributed systems where network failures cause duplicate requests.

Common Mistakes

  • Not using idempotency keys for payment APIs — network retry charges the customer twice.
  • Non-idempotent webhook handlers — message queues deliver at-least-once; handlers must be idempotent.
  • Using auto-increment IDs for operations that may be retried — each retry creates a new record.
  • DELETE not being idempotent — deleting an already-deleted resource should return 404 or 200, not an error.

Code Examples

💡 Note
Idempotent endpoints can be safely retried without double-charging. Store the result keyed by the client-provided Idempotency-Key header.
✗ Vulnerable
// Non-idempotent payment — retry = double charge:
function charge(int $userId, float $amount): void {
    $this->stripe->charge($userId, $amount); // No idempotency key
    $this->db->insert('charges', ['user_id' => $userId, 'amount' => $amount]);
}
// Network timeout → client retries → two charges

// Idempotent:
function charge(string $idempotencyKey, int $userId, float $amount): void {
    if ($this->db->exists('charges', ['key' => $idempotencyKey])) return;
    $this->stripe->charge($userId, $amount, $idempotencyKey);
}
✓ Fixed
// Idempotency key — client generates a UUID for each logical operation
class PaymentController {
    public function charge(Request $req): JsonResponse {
        $key    = $req->header('Idempotency-Key') ?? throw new BadRequest();
        $cached = $this->cache->get('idem:' . $key);

        if ($cached !== null) {
            return response()->json($cached, 200); // replay stored result
        }

        $result = $this->gateway->charge($req->amount);
        $this->cache->set('idem:' . $key, $result, ttl: 86400);
        return response()->json($result, 201);
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 40
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S
No pings yet today
Perplexity 8 Amazonbot 7 Unknown AI 3 Google 2 Ahrefs 2 Majestic 1 ChatGPT 1
crawler 23 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Design all write operations to be safely repeatable — use database UPSERT, check-before-insert patterns, or idempotency keys so retrying a failed operation never causes duplicates
📦 Applies To
any web api queue-worker
🔗 Prerequisites
🔍 Detection Hints
INSERT without ON DUPLICATE KEY UPDATE; payment processing without idempotency key; queue consumer that processes same message twice creating duplicates
Auto-detectable: ✗ No semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: File Tests: Update

✓ schema.org compliant