Answers you can trust, from Codeables
Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.
Explore CodeablesHow do I set priority fees on Solana (compute unit limit + compute unit price) for reliability during congestion?
Priority fees are how you tell the Solana network, “this transaction matters more—treat it like a priority package.” You do that by tuning two levers on the compute budget instruction: the maximum compute units you’re willing to buy, and the compute-unit price you’re willing to pay. Set them right, and your critical flows keep confirming in ~400ms even when the network is busy. Set them wrong, and you either overpay or watch important transactions sit behind cheaper traffic.
Quick Answer: On Solana, you set priority fees by adding a compute budget instruction to each transaction that (1) raises the compute unit limit to what your program actually needs, and (2) specifies a compute-unit price (in micro‑lamports per CU) high enough to outbid competing traffic during congestion. In practice, you benchmark typical CU usage per flow, add a safety buffer, then dynamically compute a price based on recent block fee levels and your business’s maximum cost per transaction.
Why This Matters
If you’re running payments, DeFi, liquidations, or any workflow where “Funds secured in ~400ms” isn’t just marketing copy, you can’t leave fee behavior to chance. Solana’s local fee markets and priority fees mean you can buy your way to predictable confirmations while the rest of the network is churning. But like any market, you need a pricing strategy—not just a hard-coded number from a tutorial.
Done well:
- Critical paths (like merchant settlement, liquidation, or large treasury moves) keep working during spikes.
- You keep fees in the sub‑cent range by paying for exactly the compute you use, not an arbitrary max.
- You avoid wasted retries, user confusion, and reconciliation nightmares caused by transactions stuck at low priority.
Key Benefits:
- Reliability under congestion: Priority fees push your transactions ahead in local fee markets when blocks are full.
- Cost control: Fine‑grained control over compute unit limits and price lets you keep median fees around ~$0.001 while spiking only when it’s worth it.
- Operational clarity: Treat priority fees as a tunable SLO: you can define “acceptable confirmation time” in code and adjust price/compute accordingly.
Core Concepts & Key Points
| Concept | Definition | Why it's important |
|---|---|---|
| Compute units (CUs) | A measure of how much work a transaction does on-chain (program execution cost). Each instruction consumes CUs; there’s a per‑tx CU limit. | CU usage governs whether your transaction can execute at all and how expensive it is. Underestimating leads to “compute budget exceeded.” Overestimating can inflate fees. |
| Compute unit limit | The maximum number of CUs the runtime will allow your transaction to consume, set via a compute budget instruction. | Raising the limit lets complex, multi‑account flows run reliably; keeping it tight prevents runaway costs and failed transactions under heavier load. |
| Compute-unit price (priority fee) | An extra fee per compute unit (in increments of 0.000001 lamports per CU) you’re willing to pay to prioritize your transaction. | This is your bid in Solana’s fee market. A higher price moves you ahead of other transactions competing for the same block, especially during congestion. |
How It Works (Step-by-Step)
On Solana, priority fees are not a separate “tip” field; they’re encoded via the compute budget program inside the transaction itself. High level:
- You estimate or measure how many compute units your program will use.
- You add a SetComputeUnitLimit instruction so the transaction can consume that amount.
- You add a SetComputeUnitPrice instruction to tell validators how much extra you’ll pay per CU.
The validator then calculates:
prioritization_fee = requested_max_compute_units × compute_unit_price
…and uses that to sort transactions in the local fee market when blocks are busy.
1. Measure and set your compute unit limit
You can’t price compute until you know roughly how much you use.
Practical approach:
- Instrument your program locally / on devnet:
- Use Solana Explorer, logs, or tools like
solana-program-testto inspect compute consumption per instruction. - Run your typical flows (simple transfer, swap, liquidation, payout batch) and record CUs.
- Use Solana Explorer, logs, or tools like
- Derive per‑flow baselines:
- Example:
- Simple on-chain transfer: ~5k–10k CUs
- Basic DeFi swap (single pool): ~100k–200k CUs
- Complex multi‑leg DeFi + oracles + memos: 500k+ CUs
- Example:
Once you have numbers, set the limit with a buffer—enough to handle small variations but not so large you’re overpaying during congestion.
Example (TypeScript using web3.js):
import {
ComputeBudgetProgram,
TransactionInstruction,
Transaction,
} from "@solana/web3.js";
// Suppose your measured median is ~200k CUs, and you want 25% headroom.
const computeUnitLimit = 250_000;
const setComputeUnitLimitIx: TransactionInstruction =
ComputeBudgetProgram.setComputeUnitLimit({
units: computeUnitLimit,
});
const tx = new Transaction().add(setComputeUnitLimitIx /*, your other ixs */);
Key points:
- If your transaction exceeds this limit at runtime, it fails with a compute budget error.
- If you set it much higher than you actually use, you increase the potential priority fee you’ll pay during congestion, because the prioritization fee formula multiplies by the requested max CU, not the actual CU consumed.
2. Choose a compute-unit price (priority fee)
Next, you set your bid per CU. Per the docs:
The prioritization fee is calculated by multiplying the requested maximum compute units by the compute-unit price (specified in increments of 0.000001 lamports per compute unit).
That 0.000001 lamports unit is often called a “micro‑lamport per CU”.
Example:
// You decide to pay 1 micro-lamport per CU during normal conditions.
const computeUnitPriceMicroLamports = 1;
const setComputeUnitPriceIx: TransactionInstruction =
ComputeBudgetProgram.setComputeUnitPrice({
microLamports: computeUnitPriceMicroLamports,
});
const tx = new Transaction().add(
setComputeUnitLimitIx,
setComputeUnitPriceIx,
/* your other ixs */
);
Your maximum prioritization fee:
max_priority_fee_lamports =
computeUnitLimit × (computeUnitPriceMicroLamports × 0.000001)
Using the 250,000 CU example at 1 micro‑lamport/CU:
max_priority_fee_lamports = 250,000 × 0.000001 = 0.25 lamports
At higher prices—for example 100 micro‑lamports/CU during extreme congestion—that same transaction could bid up to 25 lamports of priority fee. The base fee and rent behavior still apply; this is an extra fee to get priority in slot inclusion.
3. Dynamically tune fees for reliability during congestion
Static numbers don’t survive production. For reliability, tie your compute-unit price to:
- Recent network conditions: Look at cluster metrics or RPC‑exposed fee hints when available (many RPC providers expose “recommended” priority fees).
- Business value per transaction: A $10,000 liquidation can pay a higher fee than a $2 rebate.
- Latency SLOs: For flows that must confirm in ≤1s, bid more aggressively when you detect rising failure rates.
A pragmatic strategy:
-
Define classes of flows:
- Tier 1: Liquidations, expiries, large treasury moves, merchant payouts.
- Tier 2: User swaps, deposits, consumer payments.
- Tier 3: Low‑value tasks (infrequent housekeeping, low‑value airdrops).
-
For each tier, define:
- Target confirmation window (e.g., 1–2 blocks, 3–5 blocks).
- Maximum acceptable fee in USD/transaction.
-
Implement a fee controller service that:
- Monitors:
- Recent slot inclusion times.
- Your own transaction success rate at different prices.
- When possible, RPC‑provided “current median priority fee”.
- Chooses a
microLamportsvalue per tier based on:- Current cluster congestion.
- Your max cost budget.
- Monitors:
Example policy:
- Tier 1: Aim for confirmation in next 1–2 blocks.
- Start at 10 micro‑lamports/CU.
- If >5% of Tier 1 txs fail to confirm within 2 blocks over the last N minutes, double to 20, then 40.
- Tier 2: Accept 3–6 blocks.
- Start at 1 micro‑lamport/CU.
- Only raise if block congestion is sustained and user‑visible latency climbs.
- Tier 3: Keep at 0–1 micro‑lamports/CU and tolerate delays.
This is the Solana version of “surge pricing,” but controlled by you, constrained by your budget, and tuned to how critical each flow is.
Common Mistakes to Avoid
-
Setting a huge CU limit “just in case”:
How to avoid it: Measure your real CU usage and add a bounded buffer (e.g., 20–30%). Remember that your priority fee is based on the max limit, not what you actually consume, so lazy overprovisioning becomes expensive during congestion. -
Hard-coding priority prices without feedback loops:
How to avoid it: Implement basic telemetry: logcomputeUnitLimit,microLamports, outcome (success/failure), and block timings. Use that data to adjust recommended prices by tier. Don’t ship production code with tutorial values that never change. -
Ignoring RPC behavior in your reliability model:
How to avoid it: Treat poor RPC performance as equivalent to network congestion. Use private RPC for production, add retries with idempotency, and backoff when you see 429s or 5xx responses. Priority fees help with on‑chain scheduling, but they don’t fix underprovisioned RPC. -
Applying the same fee profile to all transactions:
How to avoid it: Classify flows. A $5 coffee payment and a high‑value institutional payout shouldn’t have identical fee and latency targets. Use differentmicroLamportsand CU limits per flow type. -
Not testing under load:
How to avoid it: Run synthetic load tests on devnet/testnet, mirroring your production transaction mix. Observe where your priority levels start failing and adjust policy before mainnet traffic hits.
Real-World Example
Imagine you’re running a Solana-based stablecoin payout rail for marketplace sellers. You have three main flows:
-
Instant seller payouts (Tier 1)
- Average CU usage per payout: ~150k
- Business requirement: confirm in ≤1 second for user experience parity with card “instant transfers.”
-
Buyer refunds (Tier 2)
- Average CU usage: ~120k
- OK to confirm within a few seconds.
-
Reconciliation memos & accounting adjustments (Tier 3)
- Average CU usage: ~50k
- Not time-sensitive.
You benchmark on devnet and define:
- Tier 1:
computeUnitLimit = 200_000,microLamportsdynamic:- Normal: 10
- Elevated congestion: 50–100
- Tier 2:
computeUnitLimit = 150_000,microLamports2–5 - Tier 3:
computeUnitLimit = 70_000,microLamports0–1
In production, your fee controller:
- Monitors confirmation times for each tier over a rolling 5‑minute window.
- If Tier 1 payouts start taking more than 2–3 blocks to confirm:
- Immediately raises Tier 1
microLamportsfor new transactions. - Logs the change for post‑incident review.
- Immediately raises Tier 1
During a period of heavy DeFi activity on the network, base fees rise and blocks are packed. Your Tier 3 housekeeping transactions slow down, but Tier 1 payouts continue confirming in ~400ms–800ms because their priority bids per CU are above the local median. Users still see “Instant payout complete,” and your operations team sees higher fees but within the bounds you modeled.
Pro Tip: Log both the requested and actual compute used per transaction (via program logs) along with the priority fee you paid. Over a few days of traffic, you’ll usually see opportunities to tighten CU limits and adjust tiered prices—freeing budget for critical flows without sacrificing reliability.
Summary
Priority fees on Solana are a targeted reliability tool, not a magic on/off switch. You set them by:
- Measuring how many compute units your flows actually use.
- Setting a sane
computeUnitLimitwith limited headroom. - Bidding a
computeUnitPrice(micro‑lamports per CU) that reflects how critical the transaction is and how congested the network is.
Under congestion, validators favor transactions with higher effective priority fees, especially in local fee markets. That lets you keep critical payments, liquidations, and treasury moves on a fast path while less important traffic naturally backs off. With telemetry, tiered policies, and a simple fee controller, you can keep most transactions in the sub‑cent range and only pay more when it genuinely protects business value.