Sending a Solana Transaction Signed Minutes Ago

The blockhash expires in about a minute. What to do when signing and submission are separated by approvals, bridges, or a human being.

BoltTx Team··9 min read
solanadurable-nonceblockhashtransaction-landingmultisigbackend

Most Solana documentation assumes you sign and send within the same function. A whole category of systems cannot: the signature comes from one place and the submission happens somewhere later.

Governance execution after a vote. A multisig waiting on a third approver. A bridge waiting on source-chain finality. Any backend where a human clicks Approve. ★In all of them, the getLatestBlockhash value you signed against is long gone by submission time.★

Why the Window Is So Short

A recentBlockhash stays valid for roughly 150 blocks — on the order of a minute, not an hour. Past that, validators reject the transaction outright:

Blockhash not found

★This is a rejection, not a failure.★ The transaction never executed, nothing was spent, and no state changed. It is the cleanest possible outcome, and it is also completely useless when the signature you are holding took twenty minutes to collect.

Worse, the signature is over the blockhash. You cannot swap in a fresh one without invalidating every signature you gathered. For a multisig that means going back to every signer.

Durable Nonces Remove the Clock

A nonce account replaces the blockhash with a value that does not expire until you use it.

import { SystemProgram, NONCE_ACCOUNT_LENGTH } from "@solana/web3.js";

const tx = new Transaction();
tx.add(
  SystemProgram.createAccount({
    fromPubkey: payer.publicKey,
    newAccountPubkey: nonceAccount.publicKey,
    lamports: await connection.getMinimumBalanceForRentExemption(
      NONCE_ACCOUNT_LENGTH,
    ),
    space: NONCE_ACCOUNT_LENGTH,
    programId: SystemProgram.programId,
  }),
  SystemProgram.nonceInitialize({
    noncePubkey: nonceAccount.publicKey,
    authorizedPubkey: nonceAuthority.publicKey,
  }),
);

Then every transaction that uses it follows one rule:

const nonceInfo = await connection.getNonce(nonceAccount.publicKey);

const tx = new Transaction();
// ★advanceNonce MUST be the first instruction.★
tx.add(
  SystemProgram.nonceAdvance({
    noncePubkey: nonceAccount.publicKey,
    authorizedPubkey: nonceAuthority.publicKey,
  }),
);
tx.add(...yourInstructions);

tx.recentBlockhash = nonceInfo.nonce;   // ★the nonce, not a blockhash★

★Both details are easy to get wrong and fail in confusing ways.★ If nonceAdvance is not first, the transaction is invalid. If you set an actual blockhash instead of the nonce value, you are back to a one-minute window without any warning that you lost the protection.

The Constraint That Decides Your Design

A nonce account holds exactly one nonce value, which means one in-flight transaction at a time.

sign tx A  (nonce = N)
sign tx B  (nonce = N)     ← ★same value★
tx A lands, nonce advances to N+1
tx B is now permanently invalid

★This is the single biggest source of confusion with durable nonces.★ It is not a bug. It is what makes them a replay guard: once used, that value is gone.

The consequence for architecture: one nonce account per concurrent flow. A governance system executing several proposals at once needs several nonce accounts, tracked and assigned rather than shared. Treat them as a pool.

If your delayed submission is correct and the transaction still misses, a free BoltTx key is one line to test the routing half.

Cancelling Something Already Signed

A durable-nonce transaction stays valid indefinitely, which cuts both ways. ★A signed transaction you no longer want is a signed transaction someone can still submit.★

The cancel is to burn the nonce yourself:

// Advance the nonce with a no-op. ★Any transaction signed against
// the old nonce value becomes permanently invalid.★
const cancel = new Transaction().add(
  SystemProgram.nonceAdvance({
    noncePubkey: nonceAccount.publicKey,
    authorizedPubkey: nonceAuthority.publicKey,
  }),
);

Any governance, treasury, or bridge design that can sign transactions it might later want to abandon needs this path built and tested. The nonce authority is what makes cancellation possible, so it should be held as carefully as the signing keys themselves.

When You Do Not Need a Nonce

Durable nonces cost rent, an extra account, an extra instruction, and real operational complexity. ★They are the wrong answer to a delay you can simply avoid.★

Sign at submission time. If your backend holds the key, fetch a fresh blockhash and sign right before sending. Most "delayed submission" problems are actually "we signed too early" problems.

Sign last. In a multisig, collect intent first and produce the actual signed transaction only when the final approval arrives, so the window starts at the end rather than the beginning.

Re-sign on expiry. If re-collecting signatures is cheap, expiry is an inconvenience rather than a blocker.

★Use a nonce when the signature genuinely cannot be regenerated on demand★ — offline signers, hardware wallets in a vault, approvers in other timezones, a source chain you are waiting on.

Expiry Is Not the Only Thing That Changed

This is the part that a nonce does not solve, and it deserves its own attention.

A transaction signed twenty minutes ago was built against state from twenty minutes ago. ★The blockhash problem is solved; the staleness problem is not.★

// ★Validate against current state before submitting a stale signature.★
const stillValid = await revalidate(intent);
if (!stillValid) {
  await burnNonce();          // cancel rather than submit
  await requestNewApproval(); // rebuild against current state
}

For treasury transfers this is usually fine — a transfer of a fixed amount does not care that time passed. For anything price-dependent, a nonce lets you submit a stale decision, which is worse than not being able to submit at all. Either constrain those flows to fixed amounts, or revalidate before submitting.

What Landing Looks Like

Real transactions through our delivery nodes: median confirmation 336ms — under one slot.

★A durable nonce removes the deadline but not the queue.★ Once submitted, a nonce transaction competes for inclusion exactly like any other, so if these are treasury movements or governance executions that people are waiting on, the same routing considerations apply.

Where BoltTx Fits

We handle submission. Not signing, not custody, not your approval flow.

Submissions route through our own delivery nodes in four regions with stake-weighted routing and no public mempool exposure, so a transaction is not observable in transit before it lands — which matters when the transaction is a treasury movement whose contents are worth knowing in advance.

You sign locally, whenever your process signs. We never hold funds, never sign, and never modify transaction contents. The tip travels inside the transaction, paid on chain from your own wallet, and reverts with the transaction if it fails, because that is how Solana handles atomic transactions. You pay only on transactions that reach the chain.

Get a free API key. No monthly fee:

const connection = new Connection("https://la.bolttx.io/?api-key=YOUR_KEY");

FAQ

How long is a Solana transaction valid after signing? Roughly 150 blocks from the blockhash you signed with, on the order of a minute. Past that, validators reject it with "Blockhash not found" and it never executes.

How do I send a transaction signed a long time ago? Use a durable nonce instead of a recent blockhash. The nonce value does not expire until it is consumed, so the signature stays valid indefinitely.

What is a durable nonce on Solana? An account holding a value that substitutes for a recent blockhash. It expires on use rather than on time, which is what allows signing and submission to be separated.

Why does my durable nonce transaction fail? Most often because nonceAdvance is not the first instruction, or because a real blockhash was set instead of the nonce value. Both fail in ways that do not point at the nonce.

Can I have several transactions using one nonce account? Not concurrently. A nonce account holds one value, so once a transaction consumes it, every other transaction signed against that value is permanently invalid. Use one account per concurrent flow.

How do I cancel a transaction that was already signed? Advance the nonce yourself with a no-op transaction. That consumes the value and permanently invalidates anything signed against it, which is the only reliable cancellation for a durable-nonce transaction.

Do I need a durable nonce for a multisig? Only if collecting all signatures reliably takes longer than the blockhash window. If you can produce the signed transaction at the moment of final approval, a normal blockhash is simpler.

Does a durable nonce make my transaction land faster? No. It removes the expiry deadline. Once submitted, the transaction competes for inclusion exactly like any other, so fees and routing still determine when it lands.

What does a nonce account cost? Rent exemption for its space, which is recoverable when you close the account, plus the operational cost of tracking it and one extra instruction in every transaction that uses it.

Is a stale signed transaction safe to submit? Only if the intent does not depend on state that moved. A fixed-amount transfer is fine, while anything price-dependent may have become a decision you would no longer make.

Who should hold the nonce authority? Whoever is trusted to cancel, since the authority is what allows burning a nonce to invalidate signed transactions. Treat it with the same care as signing keys.

Can I reuse a nonce account after a transaction lands? Yes. It advances to a new value and is immediately usable for the next transaction. Reuse is the normal pattern, since creating a fresh account each time wastes rent and time.

How do I check the current nonce value? getNonce on the account address returns the current value and the authority. Fetch it when building, since a value from an earlier build may already have been consumed.

What happens if two signers use the same nonce value? Whichever transaction lands first consumes it, and the other becomes permanently invalid. This is the replay protection working as designed, not a failure.

Should governance execution use durable nonces? It depends on whether the transaction is produced before or after the vote concludes. Signing after the result is known avoids nonces entirely; signing before requires them.

How do I revalidate a stale transaction before submitting? Re-check the state its correctness depends on — balances, account existence, and price if applicable. If anything moved materially, burn the nonce and rebuild rather than submitting a decision made against old state.

Back to all posts