idempotency
Skill1 starsChanged 41 days agoMITView on GitHub
Use when writing or reviewing an endpoint, webhook, message consumer, or job that can be retried or delivered more than once, especially if it creates records, moves money, or calls another service
4 other projects use a version of this.
Adopted by
Most recently taken up by
- okfriansyah-moh/agentic-workflowtheir own version, first seen Oct 25, 2026
- jars-demo/jars-skillstheir own version, first seen Oct 25, 2026
- oa2p-solutions/ecommerce-foundationstheir own version, first seen Oct 11, 2026
- Pradnyeshp/Claude-Skillstheir own version, first seen Jul 6, 2026
Other versions4 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 4
- Pradnyeshp/Claude-Skills★ 2same name
- jars-demo/jars-skills★ 0same name
- oa2p-solutions/ecommerce-foundations★ 0same name
- okfriansyah-moh/agentic-workflow★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
- snippets/CLAUDE.mdCLAUDE.md
- money-handlingSkill
- safe-migrationsSkill
- timeouts-and-retriesSkill
- transaction-boundariesSkill
The file
We split this skill into the rules it gives an agent
2 rules. 0 are common, 1 is distinctive, and 1 is very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
1
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 23
Keep keys longer than the longest possible retry window.
- Very specific: line 39
No idempotency key. If the client times out after save and retries, a second payment is created.
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Idempotency
An operation is idempotent when running it twice has the same effect as running it once. Anything reachable over a network will be retried: clients time out, gateways retry, brokers redeliver, schedulers re-run, users double-click.
When to use
- Writing or reviewing a POST or PUT endpoint, webhook receiver, queue consumer, or scheduled job.
- The operation creates a record, changes a balance, sends a message, or calls a downstream service.
Checklist
- Name the retry sources for this code path: client, gateway, at-least-once broker, scheduler, user.
- The key comes from the caller or from the message ID. It is never generated inside the handler.
- Uniqueness is enforced by the database, with a unique constraint on
(scope, key). Claim the key by inserting it before doing any work. "SELECT, then INSERT" is a race. If the side effect is only database writes, insert the key in the same transaction as the side effect, so they commit or roll back together. If the work calls other systems, insert the key in its own short transaction with statusIN_PROGRESS, do the work outside any transaction, then mark itDONEwith the response. - Store a fingerprint of the request. The same key with a different payload is a client bug: reject it with 409 or 422.
- Store the result, so a replay returns the original response instead of running again.
- Handle the in-flight duplicate and the abandoned key. A second request arriving while the first is
IN_PROGRESSmust wait or get a "processing" answer. It must not start a second copy of the work while the first is still running. If the first attempt crashed, its row never completes: give it a lease (for examplelocked_until) so a retry can take over once the lease expires, and make the work safe to resume (item 8 and the good example below). Make the lease longer than the work's own timeout, or renew it while working, so a slow attempt that is still running is never taken over. - Keep keys longer than the longest possible retry window.
- Pass a derived key downstream (for example
key + ":debit"), so the calls you make are idempotent too.
Bad example
@PostMapping("/payments")
Payment create(@RequestBody PaymentRequest req) {
Payment p = payments.save(new Payment(req.accountId(), req.amount()));
ledger.debit(req.accountId(), req.amount());
return p;
}What to flag
- No idempotency key. If the client times out after
saveand retries, a second payment is created. ledger.debitcarries no key, so a retried request can debit twice.- A crash between
saveanddebitleaves a payment with no debit, and a retry creates a second payment instead of finishing the first.
Good example
@PostMapping("/payments")
Payment create(@RequestHeader("Idempotency-Key") String key,
@RequestBody PaymentRequest req) {
return idempotency.execute("payments", key, req.fingerprint(), () -> {
// INSERT ... ON CONFLICT (idempotency_key) DO NOTHING, then load
Payment p = payments.saveOnce(key, new Payment(req.accountId(), req.amount()));
ledger.debit(req.accountId(), req.amount(), key + ":debit");
return p;
});
}CREATE TABLE idempotency_keys (
scope text NOT NULL,
key text NOT NULL,
fingerprint text NOT NULL,
status text NOT NULL, -- IN_PROGRESS or DONE
locked_until timestamptz, -- lease for IN_PROGRESS rows
response jsonb,
created_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (scope, key)
);idempotency.execute claims the key by inserting an IN_PROGRESS row with a lease, in its own short transaction. On a conflict: DONE returns the stored response, IN_PROGRESS with an unexpired lease answers "processing", and an expired lease is taken over by one conditional UPDATE ... WHERE locked_until < now(), so only one retry can win it. A fingerprint mismatch is rejected. The work runs outside any open database transaction (see transaction-boundaries), and the last step stores the response and marks the row DONE. A takeover can re-run work that partly happened, so every step must be safe to repeat: saveOnce is keyed on the idempotency key, and the downstream call carries the derived key key + ":debit".
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

