Landing Transactions Key Points
Landing a transaction means a leader includes it in a block while its recent blockhash is still valid, so the signature moves from "unknown" to a confirmed status you can show in product UX.
This page is the conceptual map for Priority Fees & Transaction Optimization - why txs stall, how CU price and limits interact, how clients retry safely, when ALTs and Jito help, and how assembly choices shape local fee markets on Agave 4.1.1.
Summary
- Inclusion is a race against blockhash expiry under leader capacity and fee competition; clients win it by bidding intelligently (priority fees / tips), requesting the right compute budget, fitting the packet (v0 + ALTs), and rebroadcasting or rebuilding with disciplined retries.
- Insight: Simulation can succeed while mainnet still drops the packet; users see "pending forever" and launches fail when landing is an afterthought instead of a product metric.
- Key Concepts: landing rate, recent blockhash / lastValidBlockHeight, compute unit (CU) limit, compute unit price (microLamports), priority fee, local fee market, address lookup table (ALT), versioned transaction (v0), Jito bundle / tip, preflight vs confirmation.
- When to Use This Model: Designing send pipelines for wallets, relayers, mints, or DeFi routes; debugging intermittent drops; setting fee and retry policy before high traffic.
- Limitations/Trade-offs: Higher bids and tips raise user cost; simulation does not reserve leader capacity; Jito and private RPC improve probability, not program correctness; over-retrying without idempotency risks double execution.
- Related Topics: Why Transactions Fail to Land, Estimating Compute Units, Setting Priority Fees, Retries & Blockhash Management, Address Lookup Tables in Practice, Jito Bundles, Transaction Assembly.
Foundations
A client builds a message (instructions, account metas, fee payer, recent blockhash), signs it, and submits the wire transaction through RPC or a block engine. The node may run preflight simulation, then forward the packet toward upcoming leaders.
Landing is inclusion in a produced block. Confirmation is how far that block has progressed through votes (processed → confirmed → finalized). Product success almost always means "landed and succeeded under the commitment you chose," not "RPC accepted the send."
sendTransaction returning a signature only proves the node accepted the submission path. The signature can remain unknown forever if the packet never wins a slot before the blockhash expires (~150 slots, often about a minute of wall clock).
| Outcome | What you observe | Typical cause |
|---|---|---|
| Never included | Status unknown / null after wait | Underpriced, dropped, expired blockhash, oversized packet, bad peer |
| Included, program failed | Signature found, meta.err set | Logic, accounts, CU exceeded during execution |
| Included, succeeded | Status at chosen commitment, no err | Healthy path |
Only the first row is a pure landing problem. CU budgeting still matters for both landing economics (price × limit) and for the second row (execution failure after inclusion).
Fees have two layers. A base fee covers signatures. A priority fee is set with Compute Budget instructions: set compute unit limit and set compute unit price (microLamports per CU). Priority lamports scale roughly with price × limit / 1_000_000. Leaders use fee signals when many transactions compete for block capacity and account locks.
That competition is often local: hot accounts (a mint vault, popular pool, shared config) create a local fee market for transactions that write those keys, even when the rest of the network is quiet.
Mechanics & Interactions
Why transactions fail to land
Leaders have finite capacity per slot. Under load they prefer higher-value work. Your transaction also races blockhash validity: after lastValidBlockHeight, validators reject the message.
Common drop paths:
- Underpriced priority relative to peers locking the same hot accounts.
- Oversized serialization (legacy messages with too many full pubkeys).
- RPC / path issues: public endpoints, packet loss, or peers that never reach the current leader.
- Stale blockhash at sign time or a retry loop that keeps an expired hash.
- Preflight false confidence: sim OK on a bank snapshot does not reserve leader capacity.
Treat landing rate (sends that reach confirmed without exhausting rebuilds) and p95 time-to-confirmed as product metrics.
Priority fees and CU price
Use getRecentPrioritizationFees (optionally scoped to accounts your transaction locks) or a provider fee API. Target a percentile: p50 quiet, p75 default UX, p90 mints and other contention. Apply a small safety factor and a hard cap so fee spikes cannot drain users.
priority_fee_lamports ≈ (microLamports_per_CU × compute_unit_limit) / 1_000_000
total_user_fee ≈ base_signature_fee + priority_fee_lamports (+ optional tip)
Price and limit multiply. A bloated CU limit with an aggressive price overpays; a tight limit with a high price still fails if execution exceeds the limit after inclusion. Fix limit from measurement first, then bid price for inclusion.
Estimating compute units
Default budgets are not tuned for your route. Simulate the fully assembled transaction, read unitsConsumed, and set SetComputeUnitLimit to roughly consumed × 1.1–1.2 headroom for state variance.
On Agave 4.1.1-era stacks, per-transaction CU ceilings are finite. Simulation that errors is a correctness problem; simulation that succeeds with high consumption is a fee and risk signal. Local tests (Anchor 0.32.1, LiteSVM, Surfpool) profile CU in development; mainnet fee percentiles still need live RPC samples.
Retries and blockhash management
Two different operations:
- Rebroadcast the same signed bytes while the blockhash is still valid (same signature, more propagation).
- Rebuild with a new
getLatestBlockhash, new message, and new signatures (different transaction identity).
Prefer application control: often low or zero RPC maxRetries, then your loop waits for confirmation, rebroadcasts the same wire form until height expiry, and only then rebuilds with a fresh blockhash and fee sample. Track lastValidBlockHeight and stop rebroadcasting after it passes. Durable nonces replace short-lived recent blockhashes for slow multi-signer flows.
Idempotency matters: if the first attempt might still land late, a second rebuild can double-execute unless the program path is safe to retry.
Address lookup tables
Versioned v0 transactions plus address lookup tables replace many 32-byte keys with 1-byte indices into an on-chain table. That shrinks packets so multi-hop swaps and multi-instruction assemblies stay under size limits leaders will propagate.
Lifecycle: create → extend with stable pubkeys → wait for activation (~1 slot) → compile v0 with lookups → optionally freeze. Clients using @solana/kit 7.0.0 fetch the ALT before compile so indices match on-chain order. ALTs do not raise priority by themselves; they remove a structural drop reason and free room for budget and tip instructions.
Jito bundles
Jito block engines accept bundles: ordered transactions that land together atomically, typically with a tip transfer. Use them when ordering and atomicity matter (mint + tip, multi-leg paths) or when public mempool exposure is unacceptable for high-value flow.
Bundles complement native priority fees; they do not replace correct CU limits or valid blockhashes. Tip markets have their own cost curve - reserve for contention windows and high-value routes.
Assembly strategies
Instruction order is part of landing reliability and fee efficiency:
- Compute budget: limit, then price.
- Setup that must precede business logic (create ATA idempotent, open accounts).
- Core program instructions.
- Optional tip / cleanup per bundle or product policy.
Compile with the right message version, complete signer set, and minimal writable account set. Over-marking writable accounts increases lock contention and can worsen the local fee market you bid into. Simulate the final wire form before mainnet send.
fetch blockhash + fee samples (+ ALT accounts)
→ prepend CU limit + price → core ixs (+ optional tip)
→ compile v0 with ALTs → sign → simulate
→ send (RPC and/or Jito) → wait commitment
unknown & hash valid → rebroadcast same bytes
expired / timed out → rebuild (new hash, fees, sign)
landed + err → fix program/accounts (do not blind retry)
landed + ok → done
Advanced Considerations & Applications
Local fee markets form around contended writable accounts. Sampling prioritization fees with the accounts your route locks often beats empty global samples when congestion is path-specific. Maintain fee profiles per template (transfer vs swap vs mint) with separate floors, percentiles, and caps.
SWQoS and private RPC improve the chance packets reach leaders. They pair with fee policy; they do not replace it. Production send paths usually want a paid tier and dual-path send for critical routes (RPC plus block engine).
Cost UX: show estimated priority SOL from price × limit, plus base fee and optional tip. Cap multipliers during spikes. Feature-flag aggressive percentiles so you can decay off-peak without a deploy crisis.
Measurement: log signature, route id, microLamports, CU limit, units consumed (sim and landed meta), tip lamports, attempts, and time-to-confirmed. Landing rate and fee per successful confirm steer percentile choice.
| Situation | Prefer |
|---|---|
| Quiet mainnet, simple ix | Modest CU price floor, standard retry |
| Shared hot accounts | Account-scoped fee samples, higher percentile |
| Large account lists | v0 + ALT maintenance job |
| Atomic multi-tx or mint day | Jito bundle + tip policy |
| Multisig / slow sign | Durable nonce |
| Sim fails | Fix program or accounts before raising fees |
Devnet caveat: fee markets and drop rates do not match mainnet. Validate assembly, ALT activation, and retry state machines on devnet; validate fee percentiles and landing SLOs with small mainnet probes.
Common Misconceptions
- "RPC returned a signature, so the transaction landed." Acceptance is not inclusion; wait for status or subscription until expiry rules say stop.
- "Zero priority fee is fine if simulation passed." Simulation does not buy leader priority; under congestion, zero-bid work starves first.
- "Max CU limit plus max price always wins cheaply." You multiply cost; right-size limit from simulation, then bid price with a cap.
- "Raising CU limit fixes landing drops." Limit prevents compute-exceeded failures after inclusion; drops need fees, size, path, and blockhash discipline.
- "RPC maxRetries alone is a retry strategy." Without fresh blockhashes and confirmation waits, you spam expired work; own the loop.
- "Legacy transactions are simpler so they land more often." Oversized legacy account lists drop; v0 + ALTs are the reliable path for fat routes.
- "Jito tips replace compute unit price." Tips incentivize bundle inclusion; native priority fees still matter for non-bundle sends and can coexist.
- "Any retry is safe." Rebuilds with new signatures can double-apply if the first tx still lands; design idempotent instructions or track in-flight state.
- "Global fee percentile equals my route's market." Local contention on your writable accounts can diverge from network-wide samples.
- "Devnet landing proves mainnet policy." Mechanics transfer; fee levels and contention do not.
FAQs
What does "landing" mean in one sentence?
A leader included your transaction in a block before its recent blockhash became invalid, so the signature is discoverable on-chain (success or program error).
How is landing different from confirmation?
Landing is inclusion. Confirmation is how many validators have voted on that block (processed, confirmed, finalized). UX usually waits for at least confirmed.
Why do transactions fail to land if simulation succeeds?
Simulation checks execution against a bank snapshot. It does not reserve leader capacity, win a fee auction, or guarantee packet propagation before blockhash expiry.
How do priority fees relate to compute unit price?
Compute unit price is microLamports per CU. Priority fee paid scales with that price times the compute unit limit you request (base signature fees are separate).
How should I estimate compute units before send?
Assemble the real transaction, simulate it, read unitsConsumed, add about 10–20% headroom, and set SetComputeUnitLimit. Details in Estimating Compute Units.
What percentile should I use for prioritization fees?
Start around p75 with a small multiplier and a hard cap for normal UX; raise toward p90 for mints and hot windows; measure landing rate and adjust. See Setting Priority Fees.
When do I rebroadcast vs rebuild with a new blockhash?
Rebroadcast the same signed transaction while lastValidBlockHeight is still ahead. Rebuild and re-sign when the hash expires or you must change fees or instructions. See Retries & Blockhash Management.
Do failed-on-chain transactions still pay priority fees?
If the transaction is included and fails during execution, inclusion fees still apply. Dropped transactions that never land pay nothing on-chain.
When should I use address lookup tables?
When account lists make legacy messages too large or leave no room for budget and tip instructions. Use v0 compilation with maintained ALTs. See Address Lookup Tables in Practice.
When should I use Jito bundles instead of a normal send?
When you need atomic multi-transaction ordering, stronger inclusion incentives via tips, or reduced public mempool exposure for high-value flows. See Jito Bundles.
What is a local fee market?
Fee pressure concentrated on transactions that lock the same hot writable accounts (pools, mints, shared vaults), which can outpace quiet global averages. Sample fees with those accounts when possible.
In what order should I assemble instructions?
Compute budget first, then account setup, then core business instructions, then optional tips or cleanup. Full patterns live in Transaction Assembly.
Does skipPreflight help landing?
skipPreflight: true can reduce latency but sends more doomed transactions. Prefer preflight on for user wallets; selective skip is for specialist low-latency paths that already simulated offline.
Can priority fees guarantee landing?
No. They raise inclusion probability under contention. Program bugs, CU exhaustion, bad accounts, expired blockhashes, and path failures still prevent success.
How do @solana/kit and Anchor fit this model?
Anchor 0.32.1 shapes on-chain programs and IDL-driven clients; @solana/kit 7.0.0 builds, signs, simulates, and sends versioned transactions. Neither removes the need for fee, CU, blockhash, and confirmation policy.
Related
- Why Transactions Fail to Land - failure categories and triage signals
- Estimating Compute Units - simulation-based CU limits and headroom
- Setting Priority Fees - percentiles, caps, and CU price strategy
- Retries & Blockhash Management - rebroadcast, rebuild, and durable nonces
- Address Lookup Tables in Practice - v0 size reduction for large account sets
- Jito Bundles - atomic tip-based landing paths
- Transaction Assembly - instruction order, packing, and compile checklist
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, and @solana/kit 7.0.0.