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:
| Reason | Frequency | Fixable? |
|---|---|---|
| Stale blockhash | Very common | Yes — use recent blockhash, retry quickly |
| Insufficient priority fee | Common | Yes — set appropriate compute unit price |
| Slippage exceeded | Common | Yes — widen slippage or execute faster |
| Compute budget exceeded | Occasional | Yes — set correct compute units |
| Network congestion | Periodic | Partially — use Jito bundles |
| Validator not reached | Occasional | Yes — 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
// 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:
// 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 allocated3. 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 Condition | CU Price | Notes |
|---|---|---|
| Low congestion | 1,000-10,000 micro-lamports | Most txs land easily |
| Normal | 10,000-100,000 | Safe for most operations |
| High congestion | 100,000-1,000,000+ | Spikes during popular mints, market moves |
Dynamic Fee Estimation
Rather than hardcoding, use recent block data to estimate appropriate fees:
// 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: 0withsendRawTransactionand handle retries yourself — the default retry logic can keep resending with a stale blockhash - Set
lastValidBlockHeightand check it before retrying
// 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.
// 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
- Use Jito bundles instead of public mempool submission
- Set compute budget correctly (not default, not max)
- Optimize priority fees based on current network conditions
- Submit to multiple regions simultaneously
- Use fresh blockhashes and submit immediately after signing
- Confirm via ShredStream for faster retry loops
- 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
- Jito Bundles guide — deep dive into bundle mechanics
- Transaction Submission reference — API details
- SSE Streams — real-time confirmation tracking
