Solana compute units: the actual cost table and how to budget
Compute units are Solana's gas. The per-syscall cost table, the per-tx limits, and how to set CU budget right to avoid overpaying for unused budget.
Compute units (CUs) are Solana's gas. Every instruction starts with a budget, every operation deducts from it, and if you run out the transaction reverts with ProgramFailedToComplete. The CU cost model is documented in the Agave runtime source but rarely surfaced as a coherent table — this article is that table.
The limits
Per-instruction default budget: 200,000 CUs
Per-transaction maximum budget: 1,400,000 CUs (1.4M)
Per-instruction explicit limit: up to 1,400,000 via ComputeBudgetProgram
Per-tx CU limit (set by client): up to 1,400,000Default per instruction is 200k. If you have 3 instructions in a tx and don't override, your tx budget is 600k. The hard ceiling is 1.4M regardless of how many instructions you have.
The cost model — where CUs go
Approximate costs from the Agave runtime (values shift across releases; check agave/runtime/src/builtins.rs for current numbers):
Operation CUs
─────────────────────────────────────────────────────
Builtin (system, vote, stake) per call ~150-3500
SPL Token transfer ~4,500
SPL Token InitializeAccount ~3,000
SHA-256 hash (per byte) ~85 (~1 CU/byte after fixed overhead)
ed25519 signature verification ~76,500
secp256k1 signature recovery ~25,000
Keccak-256 hash ~85 (per byte, similar to SHA-256)
Blake3 hash ~85 (per byte)
get_clock_sysvar / get_rent_sysvar ~10
log a message (per byte logged) ~100
log a u64 ~100
invoke / invoke_signed (overhead per CPI) ~1,000
heap allocation (per ~32 bytes) ~1
zk_token_proof verification ~50,000-200,000 depending on proof type
Pubkey::find_program_address (worst case) ~1,500 (iteration-heavy)
Pubkey::create_program_address ~1,500Most of your compute is spent on: signature checks (ed25519 is expensive), CPIs (1k each just for the overhead), hashing big buffers, and serialisation/deserialisation work. Plain math is cheap (a few CUs per opcode).
Setting the limit explicitly
Two ComputeBudgetProgram instructions exist to override defaults. Both should land before your other instructions in the transaction:
import { ComputeBudgetProgram, Transaction } from "@solana/web3.js"
const tx = new Transaction()
// Set the compute unit LIMIT for the transaction
tx.add(ComputeBudgetProgram.setComputeUnitLimit({
units: 300_000, // your measured budget + ~10% buffer
}))
// Set the compute unit PRICE in micro-lamports per CU
tx.add(ComputeBudgetProgram.setComputeUnitPrice({
microLamports: 50_000, // priority bid — see priority fees article
}))
tx.add(yourActualInstruction1)
tx.add(yourActualInstruction2)Two important rules:
- The price multiplies the allocated CUs, not the used CUs. If you set
limit = 1_400_000andprice = 50_000micro-lamports, you pay1.4M × 50,000 / 1,000,000 = 70,000 lamportsin priority fees, even if you only used 50k CUs. Overestimating the limit is expensive. - Setting only the price without the limit is a mistake. The price applies to the default budget (which may be way too high or too low). Always set both.
Measuring CU usage
Use simulateTransaction to get the real CU count for your specific instruction shape:
const sim = await connection.simulateTransaction(tx, { sigVerify: false })
console.log("CUs consumed:", sim.value.unitsConsumed)
console.log("logs:", sim.value.logs)Round up by ~10% and use that as your setComputeUnitLimit. Re-measure when your program changes or your input shape changes — CU usage can scale with input size.
The validator's side
Validators sort the mempool by CU price × allocated CUs within each write-locked account group. That product is your effective priority bid — high price × high limit beats high price × low limit even though you'd intuitively expect the per-CU price to be the sorting key.
This is also why the recommended pattern is tight limit + matching-or-aggressive price: you want to bid high per-CU to land but not pay for unused budget.
Programs that hit the ceiling
At 1.4M per-tx max, the kinds of programs that bump it:
- DEX aggregators routing through 3+ AMM pools with token transfers at each hop (each Token transfer ~4.5k, AMM math ~10-30k, CPI overhead ~1k each — adds up).
- Perpetual DEXes updating positions, funding, and oracles in one instruction.
- cNFT operations — Merkle proof verification is expensive (each level ~600 CUs, and trees can be 30 deep).
- ZK proof verification — confidential transfers, Light Protocol-style proofs.
If you're bumping the ceiling, your options are: split into multiple transactions, switch to a more CU-efficient framework (Pinocchio over Anchor), or rewrite hot paths to avoid the expensive primitives.
References
- Solana docs — Compute budget
- agave — compute_budget.rs (the canonical cost table)
- Solana priority fees — pricing CUs in 2026
Always set both the limit and the price explicitly. Measure with simulate, round up, set tight. The cost of overestimating is paid per transaction, every transaction.