OneShot

All packsSaaS Billing + Tax CoreSolve

stripe idempotency key retry double charge

An idempotency key that actually matches the request

A reused idempotency key on a changed request throws Stripe's idempotency_error; a random key on a retry does nothing at all. The pack hashes params into the key (D12).

3 of 3 runs passedOne decision inside SaaS Billing + Tax Core (nextjs-prisma-postgres).

What goes wrong

Idempotency keys are supposed to make retries of the same mutating call safe, but a key that's just a random string per call defends against nothing (every attempt gets a new key, so retries aren't deduplicated), and a key that's static per operation-and-account breaks the moment the request parameters actually change -- Stripe returns an idempotency_error rather than silently doing the wrong thing, but only once someone hits it in production.

Why agents get it wrong

"Add an idempotency key" reads like a checkbox -- generate some unique string and pass it -- rather than a design question about what should and shouldn't be treated as the same request. Getting it right requires understanding that the key needs to change when the meaningful parameters change and stay the same when they don't, which isn't obvious from the Stripe SDK signature alone.

What SaaS Billing + Tax Core pre-decides

D12 builds every mutating Stripe call's idempotencyKey from a short hash of its own parameters: `${op}:${accountId}:${hash(params)}`. A changed request naturally gets a fresh key (no idempotency_error on legitimate different retries), while an identical retry reuses the same key and dedupes correctly. Keys expire server-side after 24h; maxNetworkRetries: 2 on the client handles transient network duplicates on top of that.

Source: ARCHITECTURE.md D12

Coming soon — $149Full receipt and details for SaaS Billing + Tax Core

Related problems