An operation is idempotent when running it multiple times with the same input has the same effect as running it once.
An operation is idempotent when performing it multiple times with the same input produces the same effect as performing it once. GET is naturally idempotent; DELETE and PUT are idempotent by convention; POST is not, which is why POST endpoints that create resources need special design. In distributed systems every network call can fail, retry, and duplicate — idempotency is what turns 'the client saw a timeout so it retried' from a double-charged customer into a no-op.
The standard technique for making non-idempotent operations idempotent: require the client to send a unique key (idempotency_key or Request-Id header) with each new logical operation. The server stores the key with the result of the first successful execution. On retry with the same key, the server returns the stored result without re-executing. Stripe's API is the reference implementation; keys are typically UUIDs generated by the client, stored server-side for 24 hours or longer. This makes 'retry on network error' universally safe for the client.
Beyond API keys, the underlying writes need to be safe against duplicate execution. Techniques: unique constraints on natural keys (a payment row keyed by (customer_id, invoice_id, attempt)); INSERT ... ON CONFLICT DO NOTHING/UPDATE; conditional updates with version checks (WHERE version = expected_version). Blind INSERTs and unchecked UPDATEs are the primary source of duplicate rows and lost updates. Every write in a background job path should be reviewable against the question 'what if this runs twice?'
The hardest idempotency problems are side effects the database can't see: sending emails, calling third-party APIs, publishing events. Techniques: (a) use the vendor's idempotency support (Stripe, Twilio, most modern APIs accept idempotency keys). (b) record the intent in your database before the call, mark completed after; on retry, check the record before calling. (c) accept some duplicate emails and design the message content accordingly ('this is a copy of a message we already sent if you already received it'). Perfect exactly-once delivery across systems is theoretically impossible; the goal is 'at-most-one meaningful effect from the user's perspective.'
Related but distinct: commutativity means operations can happen in any order and produce the same result (append-only logs, set unions). Idempotency alone doesn't handle ordering — two idempotent operations applied out of order can still produce wrong state. For strong consistency, combine idempotency keys with ordering (sequence numbers) or with an event-sourcing model where the final state is derived from the ordered log. Most CRUD APIs get away with idempotency alone; systems with concurrent conflicting writes need more.
Idempotency bugs are invisible under normal load and destructive under retry storms. Test explicitly: for every write endpoint and every job, add a test that calls it twice with the same input and asserts a single effect. Chaos-testing at the infrastructure level (deliberate worker kills, simulated network partitions) catches the failure modes that unit tests don't. Idempotency is one of those properties where 'we think it works' and 'we tested that it works' are worlds apart.
Investor directory · Fundraising library · Articles A–Z · Company funding database