Idempotency means that running an operation once produces the same result as running it multiple times. If you send the same request twice and the outcome is identical — no duplicate side effects, no extra records, no double charges — the operation is idempotent.
Background jobs fail. Networks drop, servers restart, timeouts happen. When a job fails, you retry it. But here's the problem: did the job actually fail, or did it succeed and only the acknowledgment was lost?
If your job isn't idempotent, retrying it can cause real damage: duplicate emails sent to customers, double charges on credit cards, or corrupted data from applying the same transformation twice. Idempotency is what makes retries safe.
| Operation | Idempotent? | Why |
|---|---|---|
| Set user status to "active" | Yes | Same result no matter how many times you run it |
| Delete record by ID | Yes | First call deletes it, subsequent calls are no-ops |
| Upsert a row by unique key | Yes | Creates or updates — same final state either way |
| Send a welcome email | No | Each call sends another email |
| Increment a counter | No | Each call changes the value |
| Charge a credit card | No | Each call creates a new charge |
Assign a unique key to each job (usually a UUID or a hash of the job's parameters). Before processing, check if a job with that key has already been completed. If it has, skip it. Most payment APIs (Stripe, PayPal) accept an idempotency key header for exactly this reason.
Use INSERT ... ON CONFLICT UPDATE (or your ORM's equivalent) instead of plain inserts. This way, running the job twice writes the same row rather than creating a duplicate.
Before performing a side effect (sending an email, calling an API), check if it's already been done. Store a record of completed actions and skip any that already exist.
An idempotency key is a unique identifier attached to a request so the server can recognize duplicates. If two requests arrive with the same key, the server processes only the first and returns the cached result for the second. It's the standard pattern for making non-idempotent operations (like payments) safe to retry.
By design, yes. HTTP GET is defined as a safe, idempotent method — it should only read data, never modify it. In practice, some poorly designed APIs use GET for mutations, but that violates the HTTP specification.
Accept an idempotency key in the request header (e.g., Idempotency-Key). Before processing, check if you've already handled a request with that key. If yes, return the stored response. If no, process the request and store the result keyed by that ID.
Idempotency is essential when handling webhooks (which may be delivered more than once) and when retrying failed jobs with exponential backoff. Job queues rely on idempotent operations to retry safely without causing side effects.
Recuro handles cron scheduling, retries, alerts, and execution logs -- so you can focus on building your product.
No credit card required