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 (public mempool) to Jito bundle submission.

Why Bundles Land Better

  • Priority fee guarantee — bundles include a tip that goes directly to the block producer. This is more reliable than compute unit price bidding.
  • Atomic execution — the bundle either fully executes or is dropped. No partial execution, no wasted fees on failed txs.
  • Mempool bypass — bundles go directly to the block engine, not through the public mempool where they can be delayed or dropped.
  • Multi-region submission — sending to multiple block engines increases the chance of reaching the current leader.

Standard RPC vs Jito Bundles

js
// Standard RPC — goes to public mempool, hopes for the best
const sig = await connection.sendRawTransaction(tx.serialize(), {
  skipPreflight: true,
});

// Jito bundles — direct to block engine, priority guaranteed
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());

Venum submits every transaction to 5 regional Jito block engines simultaneously (~6ms submission latency). This covers validators in the US, Europe, and Asia.

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 through Venum, the tip is separate from compute unit price. Venum optimizes the tip amount automatically based on current network conditions.

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

Your App
  → Jito NY        (~6ms from US East)
  → Jito Amsterdam  (covers EU validators)
  → Jito Frankfurt  (covers EU validators)
  → Jito Tokyo      (covers Asia validators)
  → Jito Mainnet    (general fallback)

Venum does this automatically — every submission goes to all 5 Jito regional endpoints simultaneously.

6. Fast Confirmation with ShredStream

Don't poll RPC for confirmation — it adds 1-3 seconds of latency. ShredStream sees transactions in block shreds ~200ms after they land.

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

// Fast: ShredStream via Venum SSE
const source = new EventSource(
  `https://api.venum.dev/v1/stream/tx?signatures=${signature}`,
  { headers: { 'X-API-Key': API_KEY } }
);
source.addEventListener('status', (e) => {
  const { status } = JSON.parse(e.data);
  if (status === 'confirmed') {
    // ~200ms after landing
  }
});

Faster confirmation 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 public mempool submission
  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 ShredStream for faster retry loops
  7. Re-quote on retry — don't resubmit stale transactions

Venum handles items 1, 2, 3, 4, and 6 automatically. You focus on your strategy — we handle the infrastructure.

Next Steps