All articles
MEV·December 29, 2025·5 min read

Solana Priority Fees and Compute Units: MEV Searcher Optimization

Priority fees on Solana are priced per compute unit, not per transaction, making cost modeling non-trivial for complex MEV bundles. This guide covers how to minimize CU consumption while maintaining execution speed for competitive arbitrage.

Priority fees on Solana are not flat — they are denominated in microlamports per compute unit (CU), which means your effective transaction cost scales directly with how computationally expensive your instruction bundle is. For MEV searchers running multi-hop arbitrage or liquidation bots, getting this math wrong by even 10-15% compounds across thousands of daily transactions into real P&L leakage. Understanding the fee market at the CU level is not optional if you want to compete profitably.

How the Fee Market Actually Works

Every Solana transaction declares a compute unit limit via ComputeBudgetProgram.setComputeUnitLimit. If you omit this, the runtime defaults to 200,000 CUs — a number that made sense for simple SPL transfers but is either wasteful or insufficient for complex DeFi instructions. The priority fee you pay is:

priority_fee_lamports = ceil(CU_limit × microlamports_per_CU / 1_000_000)

The key insight: you are paying for the limit you declare, not the CUs you actually consume. A transaction that declares 400,000 CUs but only uses 180,000 is overpaying by 2x on priority fees. At scale — say, a bot firing 500 transactions per hour at 50,000 microlamports/CU — that overpayment is real money.

Validators select transactions greedily by fee-per-CU, so a leaner transaction with a tightly set CU limit can outcompete a sloppy one at the same absolute lamport spend. This is one of the most underutilized edges in the Solana MEV stack.

Profiling CU Consumption Before You Bid

Before you can set a tight CU limit, you need ground truth on what your instruction bundle actually costs. The standard workflow:

  • Simulate with simulateTransaction using replaceRecentBlockhash: true and parse the unitsConsumed field from the response.
  • Add a headroom buffer — 10-15% over the simulated value is typically sufficient for stable instruction paths. For bundles that touch highly contested accounts (like Raydium pools during high-volume periods), widen to 20% to account for account state divergence between simulation and landing.
  • Never use simulation results from a stale slot. If your simulation is more than 2-3 slots old on a hot path, re-simulate. The CU cost of certain programs — particularly those with dynamic compute paths based on account data — can vary meaningfully.

For complex multi-program transactions on Raydium, Orca, or Phoenix, simulating each instruction in isolation and summing gives you a ceiling, not a floor. Cross-program invocations (CPIs) add overhead that only shows up in a full-bundle simulation.

Reducing CU Consumption at the Instruction Level

The fastest path to CU reduction is usually instruction ordering and account deduplication. A few specifics from our bots practice:

Account ordering matters. Solana's runtime charges more for accounts that require deserialization passes. Placing writable accounts that are mutated early in the instruction list can reduce redundant deserialization in some program implementations. This is program-dependent and requires testing.

Minimize redundant token account lookups. If your arb path touches the same mint across multiple legs, ensure your transaction is not opening and closing ATA derivation logic multiple times. Pre-compute ATAs off-chain and pass them as explicit accounts.

Use Address Lookup Tables (ALTs) aggressively. Beyond the well-known transaction size benefit, ALTs reduce the per-account overhead in the transaction header, freeing space for more instruction data and reducing the CU budget consumed by account resolution. A v0 transaction with a well-packed ALT typically runs 5-8% leaner on overhead CUs than an equivalent legacy transaction.

Avoid unnecessary compute budget padding. Some bot templates set CU limits to 1.4M as a blanket catch-all. Unless you are running extremely deep CPI chains, this is wasteful — and on congested blocks, validators see it as a low-priority transaction relative to its declared footprint.

Bidding Strategy: Dynamic vs. Static Fee Tiers

Static priority fee tiers (low/medium/high hardcoded in config) are a liability in a dynamic fee market. Solana's fee market is localized to write-locked accounts, not global, so a congested Raydium AMM pool has a completely different clearing price than a quiet Drift perpetual at the same moment.

A production bidding strategy should:

  1. Pull recent priority fee percentiles from getRecentPrioritizationFees filtered to the specific accounts your transaction touches.
  2. Target the 75th-90th percentile of recent fees for that account set, scaling up to the 95th during detected arbitrage windows.
  3. Cap absolute spend per transaction as a function of expected profit, not as a fixed lamport value. A 0.1 SOL expected profit justifies a very different fee ceiling than a 0.002 SOL micro-arb.

This requires per-opportunity profit estimation before fee bidding — which means your execution pipeline needs a fast simulation + pricing pass before constructing the final transaction. Latency budget for this loop on competitive arb is typically under 50ms end-to-end.

Jito Bundles and the Tip vs. Priority Fee Trade-off

Jito's block engine introduces a second fee lever: the tip account transfer. When routing through Jito, your tip replaces (or supplements) the priority fee as the primary validator incentive. The mechanics differ:

  • Jito tips are a separate SOL transfer instruction, not the ComputeBudget priority fee. They are paid regardless of transaction success if the bundle lands.
  • Priority fees inside a Jito bundle still affect in-bundle ordering when multiple bundle submitters compete for the same slot.
  • For atomic multi-transaction bundles, the tip is the dominant cost; minimize CU overhead per transaction inside the bundle since you are already paying for inclusion via the tip.

The practical upshot: for Jito-routed strategies, CU optimization directly improves your margin per bundle because you are not overpaying on per-CU overhead on top of the tip. Both levers stack.

Monitoring Fee Efficiency in Production

Track fee_paid_lamports / actual_units_consumed as a per-transaction metric in your telemetry. This ratio, compared against the prevailing microlamports/CU clearing price for the accounts you touched, tells you exactly how much you overpaid on each execution. Set an alert if your average overpayment ratio exceeds 1.3x — it usually means your CU limit estimates have drifted or a program you depend on had a compute cost change after an upgrade.

Correlate this metric with landing rate by fee tier to tune your bidding model. The goal is not to minimize fees in isolation — it is to find the minimum fee that achieves your target landing probability for a given profit opportunity.


If you want a battle-tested bot architecture that handles dynamic fee bidding, CU profiling, and Jito bundle construction out of the box, see what we build and run or reach out directly.

Need a bot like this built?

We design, build and run trading bots on Solana, Hyperliquid and Polymarket.

Start a project
#MEV#Solana#priority fees#compute units#arbitrage#trading bots#optimization