From the team behind aidrop.it — one workspace to build, host, and keep changing your code.
Make order creation idempotent by assigning one key to a purchase attempt and recording its result in durable storage. A retry with the same key and input should return the original outcome. Scope the key to the authenticated customer and operation, enforce uniqueness in the database, and reject reuse with different input.
Your shop commits an order, but the customer loses the connection before receiving the response. They press the button again. The server cannot infer whether the first attempt succeeded from that second request. Disabling the button helps the interface; the database and request handler must prevent a duplicate order.
Keep one key for the whole attempt
Create a request key before the first submission and reuse it while retrying that purchase. Generate a new key for a new purchase. Associate the stored key with the customer, operation, and a fingerprint of the validated input so the server can distinguish a repeated request from an attempt to change the original action.
Authenticate the caller before returning a recorded result. Someone who knows a key must not gain access to another customer's order. Define what the client receives while the first request is still processing, and retain the record for the retry window your application supports. Treat a timeout as an unknown outcome until you check it.
Commit the key and order together
Record the request key and order in one database transaction, with a unique constraint on the key's scope. Two concurrent handlers can both pass an application-level existence check. Let the database enforce the winner, then have the other handler read the committed result or return the documented in-progress response while the first handler completes.
PostgreSQL's unique constraints can enforce a combination such as customer, operation, and request key. Require those fields rather than allowing null keys. The transaction also needs the order's line items and recorded outcome, so a process failure cannot leave a completed deduplication record without its order.
Keep the request record authoritative in the database rather than an expiring cache. Process memory loses that evidence on restart; cache expiry can remove it before a delayed retry arrives.
Give the payment its own repeat-safe operation
A database transaction cannot cover a request to an external payment provider. Use the provider's idempotency mechanism for the payment action and associate its key and reference with your order. Retry that action with the same parameters and key; a new key after a timeout can create another payment while the first one already exists.
Stripe's idempotent request contract records the first executed result, compares parameters on reuse, and returns that result for later matching requests, including a stored error. Its key retention has a boundary. Check the provider's contract and reconcile an uncertain payment before retrying beyond that boundary.
Track order acceptance and payment status as separate facts. A background-work record can hold a pending payment step without keeping the customer's HTTP request open. Reconcile the payment before marking that step complete. The payment webhook check covers verified confirmations, duplicate deliveries and fulfillment after acknowledgment.
A duplicate-request acceptance check
Run these checks against a test environment before relying on retries in production. Use one customer, a fixed purchase payload, and a recorded key so you can compare both responses with the database. Add a concurrent submission and a process restart: a sequential second click does not exercise either of those failure cases.
ORDER RETRY CONTRACT
Operation and authenticated customer scope:
Request-key field and validated-input fingerprint:
Unique database constraint:
In-progress response and retry interval:
Retention window and handling after it expires:
Payment key, provider reference, and reconciliation owner:
[ ] Same key + same input returns the original order
[ ] Same key + changed input returns a conflict
[ ] Another customer cannot retrieve that result
[ ] Two concurrent submissions create one order
[ ] Retry after commit but lost response returns that order
[ ] Retry after process replacement still returns that order
[ ] Payment timeout uses the existing key and reference
Record order count and payment count for each case.
FAQ
What does an idempotent request mean? Repeating the same logical request preserves the intended business effect. For order creation, matching retries return the recorded outcome instead of creating additional orders. The server must define the key's scope, input checks, and retention window.
Can I use a timestamp as the request key? A timestamp generated for each retry identifies separate attempts and defeats deduplication. Generate a collision-resistant key for the purchase attempt, keep it through retries, and generate another for the next purchase.
Does aidrop.it make my API idempotent? aidrop.it runs your application's code and can provide an attached PostgreSQL resource. Your code owns the request-key contract, database constraint, and payment reconciliation. Hosting the database preserves those records across application deployments; it does not implement the order handler.
Get it running from the session you are already in
Connect your coding agent over MCP and ask it to deploy. aidrop builds the repository and runs it on a public address; when a build or the app fails, the log says why, and your agent fixes it and builds again.