Skip to content

How to Improve Solana Transaction Landing Rate

Getting a transaction submitted is only half the battle on Solana. The other half is making sure it actually lands in a block. This guide covers the key factors that affect transaction landing rate and how to optimize them.

Why Transactions Fail to Land

Solana transactions can fail to land for several reasons:

ReasonFrequencyFixable?
Stale blockhashVery commonYes — use recent blockhash, retry quickly
Insufficient priority feeCommonYes — set appropriate compute unit price
Slippage exceededCommonYes — widen slippage or execute faster
Compute budget exceededOccasionalYes — set correct compute units
Network congestionPeriodicPartially — use Jito bundles
Validator not reachedOccasionalYes — multi-region submission

Most failed transactions come down to three things: timing, fees, and submission method.

1. Use Jito Bundles Instead of sendTransaction

The single biggest improvement you can make is switching from sendTransaction on a standard public path to Jito bundle submission.

Why Bundles Land Better

  • Direct block-engine path — bundles include a tip that goes directly to the block producer, which can be more reliable than compute unit price bidding alone.
  • Atomic execution — the bundle either fully executes or is dropped. No partial execution, no wasted fees on failed txs.
  • Direct submission — bundles go directly to the block engine instead of relying on the usual public submission path.
  • Multi-region submission — sending to multiple block engines increases the chance of reaching the current leader.

Standard RPC vs Jito Bundles

js
// Standard RPC — standard public submission path
const sig = await connection.sendRawTransaction(tx.serialize(), {
  skipPreflight: true,
});

// Jito bundles — direct to block engine
const result = await fetch('https://api.venum.dev/v1/swap', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY },
  body: JSON.stringify({
    transaction: Buffer.from(tx.serialize()).toString('base64'),
    quoteId: build.quoteId,
  }),
}).then(r => r.json());

Teams that care about landing quality often prefer bundles or other dedicated submission paths instead of relying on a single public RPC endpoint.

2. Set Compute Budget Correctly

Every Solana transaction has a compute unit (CU) budget. If your transaction exceeds it, it fails. If you set it too high, you waste priority fee.

Common Mistakes

  • Default CU limit (200K) — some swap transactions need 300-500K CU. If you don't set it, the default may not be enough.
  • Excessive CU limit (1.4M) — setting the max wastes your priority fee since fee = CU_limit * CU_price.

Right Approach

Simulate first, then set CU slightly above what the simulation consumed:

js
// Venum handles this automatically — the returned transaction
// already has optimized compute budget instructions
const { transaction, computeUnits } = await fetch(
  'https://api.venum.dev/v1/swap/build',
  { /* ... */ }
).then(r => r.json());

// computeUnits tells you exactly what was allocated

3. Optimize Priority Fees

Priority fees (compute unit price) determine where your transaction lands in the block. Too low and you get dropped during congestion. Too high and you overpay.

Fee Strategy

Network ConditionCU PriceNotes
Low congestion1,000-10,000 micro-lamportsMost txs land easily
Normal10,000-100,000Safe for most operations
High congestion100,000-1,000,000+Spikes during popular mints, market moves

Dynamic Fee Estimation

Rather than hardcoding, use recent block data to estimate appropriate fees:

js
// Get recent priority fee levels
const fees = await connection.getRecentPrioritizationFees();
const median = fees
  .map(f => f.prioritizationFee)
  .sort((a, b) => a - b)[Math.floor(fees.length / 2)];

When using Jito bundles, the tip is separate from compute unit price.

4. Handle Blockhash Expiry

Solana blockhashes expire after ~60 seconds (150 slots). If your transaction isn't included by then, it's gone.

Best Practices

  • Get the blockhash as late as possible — right before signing, not minutes ahead
  • Use maxRetries: 0 with sendRawTransaction and handle retries yourself — the default retry logic can keep resending with a stale blockhash
  • Set lastValidBlockHeight and check it before retrying
js
// Get fresh blockhash right before signing
const { blockhash, lastValidBlockHeight } =
  await connection.getLatestBlockhash('confirmed');

// Set it on the transaction
tx.message.recentBlockhash = blockhash;
tx.sign([wallet]);

// When retrying, check if blockhash is still valid
const currentHeight = await connection.getBlockHeight();
if (currentHeight > lastValidBlockHeight) {
  // Blockhash expired — rebuild with new blockhash
}

When using Venum's /v1/swap/build, the transaction comes with a fresh blockhash. Submit it promptly after signing.

5. Multi-Region Submission

Solana's leader schedule rotates among validators worldwide. If you only submit to one RPC endpoint, your transaction might need to hop across the network to reach the current leader.

Why This Matters

  • Solana block time is ~400ms
  • Network propagation between regions can take 50-100ms
  • Missing one leader slot means waiting for the next one

Solution: Submit to Multiple Endpoints

Submitting through multiple viable channels can improve the odds of reaching the right path in time. If you do not want to build that plumbing yourself, Venum's transaction sending endpoint can help handle the submission step.

6. Fast Confirmation with Pre-Confirmation Stream

Don't poll RPC for confirmation — it adds 1-3 seconds of latency. Venum's transaction stream gives you a fast processed signal and an optimistic early landed signal, both well before finalized RPC state.

js
// Slow: polling RPC
const confirmation = await connection.confirmTransaction(signature); // 1-3s

// Fast: pre-confirmation via Venum SSE
const source = new EventSource(
  `https://api.venum.dev/v1/stream/tx?signatures=${signature}&events=landed,processed&apiKey=${API_KEY}`
);
source.addEventListener('tx', (e) => {
  const { status } = JSON.parse(e.data);
  if (status === 'processed') {
    // fast post-submit visibility without raw RPC polling
  }
});

Faster transaction visibility means faster retry on failure, which means higher effective landing rate.

7. Retry Strategy

When a transaction fails, how you retry matters:

Do

  • Re-quote before retrying — pool state changes every block. Your original quote may be stale.
  • Get a fresh blockhash — never retry with the same blockhash.
  • Back off on rate limits — if you're hitting 429s, slow down.
  • Check the error — some failures aren't retryable (insufficient balance, invalid account).

Don't

  • Don't retry the exact same transaction — if it failed on-chain, the same inputs will fail again.
  • Don't retry indefinitely — set a max retry count (2-3 is usually enough).
  • Don't retry on slippage errors without re-quoting — the price has moved, your original route is stale.

Summary: Landing Rate Checklist

  1. Use Jito bundles instead of relying only on a standard public submission path
  2. Set compute budget correctly (not default, not max)
  3. Optimize priority fees based on current network conditions
  4. Submit to multiple regions simultaneously
  5. Use fresh blockhashes and submit immediately after signing
  6. Confirm via pre-confirmation stream for faster retry loops
  7. Re-quote on retry — don't resubmit stale transactions

Venum can help with the submission path and transaction lifecycle plumbing so you do not have to build all of that yourself.

Next Steps