Does AdonisJS provide built-in idempotency-key handling for transaction retries?
0 reputation · 26 Feb 2022, 17:27 UTC
0 reputation · 26 Feb 2022, 17:27 UTC
When a client retries a write request after a network timeout, the server may have already committed the transaction before the response was lost. Lucid transactions roll back only when the callback throws, so a client-side timeout does not guarantee the work was aborted. Without a deduplication mechanism, the retry can create a duplicate record even though the original write succeeded.
The common workaround is to require a client-generated idempotency key, store it with a unique index, and short-circuit the controller when the key already exists. However, the framework does not appear to ship with middleware or a trait that automates this pattern across routes.
Is there a first-party feature in AdonisJS 6 (or 5) that automatically detects and ignores repeated writes based on an idempotency header? If not, which approach is recommended for persisting the key—inside the same transaction as the business write or in a separate lightweight table? How should the response for a duplicate key differ from the initial success to let the client reconcile safely?
35275 reputation · 26 Feb 2022, 19:24 UTC
No. In the established AdonisJS 5 and 6 line, there is no first-party middleware, trait, or Lucid feature that automatically detects an idempotency header and ignores repeated writes. You must implement deduplication in application code.
Confirmed: Lucid’s db.transaction() rolls back only when the callback throws. If the commit succeeds and the HTTP response is lost, the write is already durable; a client-side timeout does not undo it.
Likely explanation: AdonisJS leaves idempotency to the application because the correct scope—per user, per tenant, per endpoint—and the replay policy vary too much across apps to enforce safely in the core.
Idempotency-Key header).db.transaction() as the business write, insert a row into an idempotency_keys table. Add a unique index scoped by tenant/user/endpoint and store a hash of the request payload.SELECT first is only an optimization; concurrent retries can both pass the check before insert.Idempotency-Replayed: true.SET NX; a crash between the business commit and the key write leaves a duplicate window.Grep your installed packages and application middleware for first-party support:
grep -ri "idempotency" node_modules/@adonisjs app/middleware --include="*.ts" --include="*.js" -l
Then simulate a lost response by calling the endpoint twice with the same key and assert one business row and one key row. Add the unique index in a migration and run two concurrent duplicate inserts to confirm exactly one succeeds and the other raises a unique violation your handler maps to replay/conflict.
What exact AdonisJS version are you running (for example, 6.x.y)? A newer minor or patch release could add first-party support even though the established 5/6 line does not include it, so the exact version determines whether this answer needs review.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.