Transaction Queue
The transaction queue lets an integrator submit a blockchain write once and retry it safely, without ever risking a duplicate broadcast to the chain.
The queue's own job is acceptance and deduplication. What settlement means once execution finishes belongs to the settlement verdict.
The queue deduplicates a transaction request that reaches it with the same idempotency key, sender, chain, and wallet selection within 24 hours. A route may do other work before it reaches the queue, so check that route's replay contract and the original request status before resubmitting. See Idempotent Write for the exact replay rules.
Acceptance answers immediately; settlement is the answer that counts. The queue confirms a submitted write right away, and durable execution broadcasts, confirms, and reports the outcome once the chain settles it, so a fast acceptance is never read as proof the transaction happened.
A stalled or failed transaction is recoverable, and one sender's stuck write never blocks another sender's. Ordering is scoped to a sender, chain, and organization; automatic recovery resolves transient failures, and an operator can force a retry, a failure, a cancellation, or a nonce correction when it cannot.
Why every write needs a queue
Every operation the platform performs against a ledger ends the same way: a signed write broadcast to a blockchain. Issuing supply, freezing a holding, paying a coupon, and settling a trade are all, underneath, one more write to a chain that charges gas whether the write succeeds or fails. A caller that resubmits a write because a connection dropped or a request timed out can turn one intended mint, transfer, or freeze into two. A doubled transfer is not a display bug for a regulated operator. It is a real balance change on chain, with a reconciliation gap behind it.
More than one caller can submit work for the same sender at once. An operator working in the Console, an integrating API client, and a workflow step reacting to an earlier event can all sign against the same wallet, on the same chain, in the same minute. Every write from one sender needs a nonce, the wallet's own increasing sequence number, and two writes that reuse the same nonce from the same sender cannot both land: the chain accepts one and rejects the other. Without one place that serializes that sequence per sender and chain, concurrent callers compete for the same slot instead of queuing behind it.
Every accepted instruction needs a durable record of what was asked, what was attempted, and what the chain answered, plus a path back when a transaction stalls instead of confirming. The rest of this page is that record, that ordering, and that path back.
Why one queue for the whole platform
The alternative is each domain that writes to a chain, asset issuance, custody, trading settlement, and workflow steps among them, building its own retry, nonce, and recovery logic against the chain. Each separate implementation is its own chance to double-broadcast a write or collide two nonces. A defect in one domain's retry logic rarely resembles a defect in another's, so fixing one teaches an operator little about the rest.
The platform instead funnels every on-chain write, from every domain, through this one queue. No other package broadcasts a transaction on its own. An instrument's own servicing operations queue the same way a trading venue's settled trade does; see Asset Lifecycle for the full list. One guarantee against double-broadcast and one ordering rule then applies the same way, no matter which domain asked for the write.
Acceptance is not settlement
Submitting a write to the platform gets a fast answer, but that answer is acceptance, not proof the transaction happened. The queue's job is to record the intent, make sure a retried request never turns into a second broadcast, and hand the accepted work to durable execution. What actually happened, confirmed, failed, or something in between, is reported separately once execution finishes; see Settlement VerdictA Settlement Verdict lets you report success only when an operation actually happened, not from acceptance alone, across four recorded end states.Read the concept for what that terminal report means.
Deduplication is the queue's other half of the promise. Once a write reaches the queue, a matching submission with the same key, sender, chain, and wallet selection within 24 hours resolves against the existing transaction request. While the work is in flight, the queue attaches to it; once it has completed, the queue reads back its recorded result. Against a transaction that failed, dead-lettered, or was cancelled, the queue refuses the duplicate key rather than replaying it. This rule does not cover work an API route performs before queue admission. Check the original outcome and transaction references before starting a new attempt.
What an operator sees, and one name not to confuse it with
An operator sees this queue in exactly one place: the Console's transaction table, an organisation-wide view across every wallet, not just the caller's own. It shows a transaction's current status, dead letter included, with a secondary line underneath for finer detail. When automatic recovery cannot resolve a stuck or failed row, an operator can step in directly rather than wait on the schedule; the levers available there are the same ones covered in What the operator API adds beyond acceptance.
The Console also has a separate operator work queue, unrelated to this page, for bond maturity, redemption approvals, and KYC review. It shares the word queue with this page's subject and nothing else; the two systems do not overlap, and a runbook about one does not apply to the other.
Ordering, delivery, and what happens when work stalls
Once a write is accepted, two more guarantees apply: where it sits in line, and what happens if it never confirms. The platform serializes execution per sender, per chain, per organisation, so a pending nonce for one sender does not reserve another sender's nonce sequence. Shared network or service capacity can still delay both.
Delivery to the chain is at-least-once, not exactly-once: the same accepted row can be resubmitted more than once over its life. The platform checks the row's state and tracks the sender's nonce to coordinate retries and replacements. Those controls do not make an independently submitted request a safe retry. A transaction can stall with no confirmation, or it can fail in a way execution already knows will not change on retry. Both eventually land on dead letter, but by different routes and on different budgets: requeued repeatedly by a reconciliation sweep that runs on a five-minute cycle in the first case, skipped straight there in the second. The recovery-path figure draws both paths, along with the one way out of dead letter once a row is there.
Both routes end the same way: an operator's forced retry is the only door out of dead letter, and it treats the row as fresh rather than resuming where it stalled.
What each outcome leaves you
A transaction has four terminal states. Pending is an intermediate state, including after a synchronous wait ends. A still-pending result after your synchronous wait only means the wait budget ran out, not the work; execution continues underneath it. Completed means the chain settled the work with a recorded outcome. Execution rejects a failed transaction outright, and dead letter means recovery gave up, or hit a failure that retrying cannot fix. The two look interchangeable at a glance, but they are not quite the same, as the paragraph after the table explains. Cancellation withdraws a row before execution finishes.
| What you see | What is still possible |
|---|---|
| Still pending after your synchronous wait | Read back the status URL the response carried, until the transaction reaches a terminal state. The queue deduplicates a matching submission, but repeat the API request only when its route documents replay safety. |
| Completed | Nothing. The row stays closed; the platform blocks a forced retry against it. |
| Failed | An operator can force a retry. You can submit a fresh attempt yourself under a new idempotency key. |
| Dead letter | The same two options as failed. The row does not requeue itself. |
| Cancelled | The platform blocks a forced retry. A fresh attempt needs a new idempotency key. |
Between force-retry and a fresh attempt, the choice turns on what you have already confirmed. A forced retry keeps the row's identity, its idempotency key included, so it is the right lever when you want the same logical operation to continue under its original name; only an operator can pull it. Before using a new key, read the original terminal state and inspect its transaction references if the chain outcome is uncertain. Do it earlier and the new key broadcasts independently, even if the original request already succeeded: exactly the hazard the FAQ on resubmitting under a new idempotency key walks through.
A forced retry is not a resume. It requeues the row from the start, clears the recorded error, and resets the retry count, so the row gets a full budget again rather than the remainder of a spent one. That is why it is an operator's decision rather than an automatic one: whatever exhausted the first budget is usually still true.
Nothing about any of this rewrites the row's past. The platform appends each forced transition to the row's own history, so the trail shows the state it came from and who moved it, and a reopened transaction stays visibly a reopened transaction.
What the operator API adds beyond acceptance
The queue admits one accepted instruction per sender, chain, and idempotency key. A second submission of the same triple is not an error: it signals that the work already exists, so the queue attaches it to that work rather than broadcasting again, following the exact replay rules in Idempotent Write. Once accepted, asynchronous is the default: the call returns immediately with a handle rather than waiting on anything. A caller can opt into a bounded synchronous wait instead, clamped by whatever time the request has left. Past that budget, or by default, the response degrades to an async-accepted handle, the transaction's identifier and a status URL to read it back with, rather than failing the call. A synchronous caller that hits its budget receives a pending result, not a rejection. The exact wait budget and its limits are in the API reference.
The platform classifies deterministic validation or contract failures separately from temporary faults. A recognized gas, account prefund, or paymaster-deposit shortfall is excluded from terminal classification so the funding flow can pause and retry after a top-up. Recovering a stuck or dead-lettered row outside its automatic recovery is an operator-only step: a force-retry, a force-fail with a recorded reason, a cancel, or a force-nonce correction, each scoped to exactly the failure mode it exists to fix.
What a stalled or failed transaction does not mean
A dead-lettered transaction is not a lost transaction. Its row and its full history persist and stay visible in the operator-facing transaction table until someone acts on it; reaching dead letter does not delete evidence of what the caller attempted. A queue timeout on a synchronous call is not a rejection either; the work continues under durable execution, and the platform hands the caller a handle to check later rather than a definitive failure. Reporting either of these as a hard failure overstates what the platform actually recorded.
The platform scopes a wallet-balance shortfall error to the caller's own resolved executor wallet, never a shared Operator WalletAn operator wallet lets your users transact without holding native gas: the platform pays the network fee, and you fund and monitor the wallet that covers it.Read the concept funded by the platform itself and never another participant's address. That scoping is what keeps a routine gas-shortfall report from becoming an unintended disclosure of a different party's wallet identity.
Frequently asked questions
Does resubmitting under a new idempotency key ever create an unwanted duplicate?
Yes, and that is by design. The queue's protection covers a repeated key against the same sender and chain; the platform treats a new key as a new intent, not a retry, so it broadcasts on its own even if the original request already succeeded. If a caller mints a new key without first reading back the original transaction's status, the platform has no way to recognize the two as the same work, and both proceed.
Does the same idempotency key protect a retry across two different chains?
No. The queue deduplicates on the sender, the chain, and the idempotency key together. The same key on a second chain is a different triple, so it starts an independent accepted instruction there rather than attaching to the first chain's work. A caller retrying one logical operation across more than one chain needs a separate key per chain, matching the way the platform already scopes ordering.
Does forcing a retry give a failed or dead-lettered transaction a new idempotency key?
No. Force-retry initially applies only once a row has reached Failed or Dead letter; a still-stalled row keeps recovering on the automatic schedule instead. If the retry requeued the row but could not start execution, repeating force-retry on that unclaimed Queued row resumes its attempt or starts a new attempt if the earlier run ended. What it does is requeue the same row rather than create a new one, so the row keeps its original sender, chain, and idempotency key. Everything about its execution resets: state, retry count, recorded error, revert and contract or RPC error detail, the signed transaction, hash, confirmation count, and receipt, and the operator's payload overwrites its nonce and gas price. See Idempotent Write for the wallet-selection fingerprint a requeued row still carries forward unchanged.
Why can an operator reopen a failed transaction but not a completed one?
Completion means the chain accepted the work, so reopening a completed row would mean broadcasting a second transaction for something that already happened, which is exactly what the queue's replay rules exist to prevent. A failed or dead-lettered row can be requeued after its cause is resolved. Inspect the recorded transaction and chain receipt first when the actual outcome is uncertain.
Transaction Lifecycle
The Transaction Lifecycle gives every write one auditable path to its outcome, so a same-key retry never leaves it unrecorded or runs it twice.
Settlement Verdict
A Settlement Verdict lets you report success only when an operation actually happened, not from acceptance alone, across four recorded end states.