Solana network congestion: what is actually scarce

Congestion is the most used and least defined word in Solana trading. It is not a queue you are waiting in, it is a competition you are losing, and the thing you are competing for is narrower than most people assume.

The Network Conditions Desk 2477 words 12 min read Updated 4 September 2026
scarce resource block space Compute units inside one leader block, not bandwidth in general
narrower still write locks Exclusive write access to one account inside that block
failure mode dropped Not included is the normal outcome; there is no waiting room
price signal local The fee market is per account, not one number for the chain

Congestion on Solana means that more transactions want to be in a block than that block can hold. It is competition for a fixed amount of space during a fixed window of time, resolved by the leader that is producing at that moment. It is not a queue, there is no position in line, and the ordinary outcome for a transaction that loses is that it is never included at all.

That distinction changes what you should do about it. You cannot wait out a competition you are not entered in. You can enter it differently, enter it at a different size, or decline to enter it while the odds are bad.

What congestion is competing for

Solana produces blocks on a schedule. Slots are allocated to leaders in advance, the protocol targets a slot duration of four hundred milliseconds, and each block carries a bounded amount of work. The bound is expressed in compute units, which is the accounting unit the runtime uses for execution cost, and the protocol publishes limits at three separate levels: how much compute a whole block may contain, how much may be spent writing to any one account, and how much a single transaction may request.

Those limits are parameters rather than laws of nature. They have been raised through the network's public change process and may be raised again, which is exactly why this desk does not quote the current values as if they were permanent. What matters for a trader is the shape they impose. There is a ceiling per block, a stricter ceiling per contended account, and a ceiling per transaction, and every one of them can be the thing you hit.

There is also a hard limit on the size of a transaction in bytes, inherited from the packet size the network transports transactions in. A transaction that grows past it is rejected before any of the compute accounting applies. Large routes with many accounts run into this constraint long before they run into a compute one, which is why complex multi-hop swaps fail in a way that looks like congestion but is really a packaging problem.

The authoritative descriptions of transaction structure, fees and limits live in the Solana protocol documentation, and they are worth reading in the original rather than through any summary, including this one.

Write locks make the bottleneck narrower

Solana executes transactions in parallel by requiring every transaction to declare, in advance, which accounts it will read and which it will write. Two transactions that touch disjoint account sets can run at the same time. Two transactions that both write the same account cannot, and the runtime serialises them.

This is the single most useful mechanism to understand when your trades fail. A liquidity pool is an account. When a token has everyone's attention, the transactions competing to trade it are all writing the same handful of accounts, so they are all serialised against each other and all charged against the same per-account compute allowance. The rest of the chain remains available. Your pair is the congested part of the network, not the network.

It also explains a pattern that confuses people the first time they see it. You send two transactions, one on the contended pair and one on something quiet, and only one lands. Nothing is wrong with your endpoint or your signing. The quiet transaction had a resource nobody else wanted, so it was scheduled immediately.

The practical consequence

When you are being rejected repeatedly, ask which account is contended rather than whether the network is busy. If the answer is one pool, then routing, sizing and timing are levers available to you. If the answer is everything you touch, you have probably left congestion and entered a different condition, and the response is not the same.

Dropped rather than delayed

Solana has no mempool. There is no shared pool of pending transactions that leaders draw from at their leisure, and no queue in which your transaction acquires seniority. Clients forward a signed transaction to the leader for the current slot and to leaders scheduled shortly after it. A leader that cannot fit the transaction does not hold it for a colleague; the transaction is simply absent from the block.

Two things follow. First, the failure you experience most often during congestion is silence rather than an error: nothing on chain says your transaction was rejected, because from the chain's point of view it never happened. Second, there is a deadline. Every transaction references a recent blockhash, and a blockhash is only accepted for a bounded window of blocks after it was produced. Once that window passes, no leader will accept the transaction, and the attempt is permanently dead.

The window is generous by human standards and short by machine standards. The published limit is one hundred and fifty blocks, and at a four hundred millisecond target slot that is sixty seconds of arithmetic before any skipped slots are taken into account. Treat that as a design constraint rather than a measurement: a retry strategy that takes longer to give up than the blockhash takes to expire is retrying something that cannot succeed.

The ingestion path itself is also a shared resource. Validators accept transactions over a connection-oriented transport with per-source limits that are weighted by stake, so a client with no stake behind it competes for ingestion capacity as well as for block space. The operational details are documented by the maintainers of the Agave validator client, and they matter more during contention than at any other time.

The local fee market

Every transaction pays a base fee per signature, which is a published protocol constant and does not move with demand. On top of that, a transaction may declare a priority price using the compute budget instructions: one instruction sets the compute unit limit the transaction is requesting, and another sets the price it is willing to pay per compute unit.

The resulting priority fee is the product of those two numbers, and it is what the leader's scheduler uses to rank competing transactions. Crucially, the competition is local. Because contention is per account, the price it takes to be included when writing a saturated pool has nothing to do with the price it takes elsewhere in the same block. There is no single number that describes the cost of using Solana at a given moment, and any dashboard that presents one is averaging across markets that are not connected.

The two levers behave differently. Raising the price makes each attempt more expensive without changing how much space you need. Lowering the requested compute limit makes each attempt cheaper and makes you easier to fit into a block that is nearly full. Operators who only ever reach for the price lever end up paying more for a transaction that is still awkward to schedule.

Fee posture is also where budgets quietly disappear. If you are running an automated flow, the per-attempt figure is much less interesting than the per-hour figure, and the honest way to look at it is to multiply your priority fee by the number of attempts your retry logic is capable of making. Anyone evaluating a hosted tool should do the same arithmetic before comparing platforms, because published headline pricing and realised Solana volume bot cost diverge exactly when conditions are worst.

A worked fee calculation

The arithmetic below is illustrative. The prices are assumptions chosen to show how the formula behaves, not observations of any market, and the only fixed inputs are published protocol constants: one SOL is one billion lamports, a micro-lamport is one millionth of a lamport, and the base fee is five thousand lamports per signature.

The priority fee in lamports is the requested compute unit limit multiplied by the price in micro-lamports per compute unit, divided by one million. A transaction requesting two hundred thousand compute units at a price of ten thousand micro-lamports therefore pays two thousand lamports in priority fees, plus the base fee.

Requested CUPrice (micro-lamports per CU)Priority fee (lamports)Total with one signatureTotal in SOL
200,0001,0002005,2000.0000052
200,00010,0002,0007,0000.0000070
200,000100,00020,00025,0000.0000250
200,0001,000,000200,000205,0000.0002050
600,0001,000,000600,000605,0000.0006050

Read the last two rows together. Tripling the requested compute limit triples the fee at the same price, for a transaction that may not have needed the extra room at all. Measuring actual consumption through simulation and requesting a limit slightly above it is the cheapest optimisation available, and it is available before you have spent anything.

Now extend the same arithmetic across a session. A routine that makes four attempts per minute at the fourth row's price is spending roughly 0.049 SOL per hour in fees alone, whether or not any of those attempts land. That figure is arithmetic from the assumptions above and nothing else, and it is the number that decides whether a strategy survives a bad afternoon.

Symptom and cause

The table below maps what you see to what is happening underneath. It is deliberately written in the words traders use rather than the words the documentation uses, because the translation is where most diagnostic time is lost.

What you seeMost likely causeWhat it is notFirst thing to change
Transaction vanishes with no on-chain recordNever included; blockhash expired before a leader took itA silent rejection by your endpointShorten the retry window to fit the blockhash lifetime
One pair fails repeatedly, others landWrite contention on that pool's accountsA chain-wide conditionReduce size, widen the deadline, consider another venue
Fees rise but inclusion does not improveCompeting for a saturated account, not for block spaceEvidence that fees do not workStop escalating price; reduce requested compute instead
Large routed swap rejected instantlyTransaction size or per-transaction compute ceilingCongestion at allSplit the route or use address lookup tables
Everything fails, including trivial requestsEndpoint, path or a cluster-level conditionCongestion on your pairRun the isolation sequence before changing anything

Why two traders disagree about congestion

Locality explains almost every argument about whether the network is congested. One trader is writing a pool that thousands of people want in the same slot. Another is writing a pool nobody is looking at. Both describe the same chain, at the same moment, in opposite terms, and both are reporting accurately.

Aggregate charts make this worse rather than better. A single chain-wide figure for fees or failures blends saturated markets with quiet ones, so it under-reports the condition you are actually in and over-reports the condition your neighbour is in. If you want a number that describes your situation, it has to be measured on the accounts you are touching.

The same effect appears in reverse when a widely watched launch settles. Contention decays unevenly, and the pools that stay contended longest are the ones with the most attention rather than the most volume. A trader who left early will tell you it cleared; a trader still working the same pair will tell you it did not.

What congestion is not

Three conditions get filed under the same word and should not be.

  • Degradation. A period where blocks are still produced but the experience of using the chain worsens across the board, rather than on one contended account. The unevenness is across time instead of across venues.
  • An incident. A cluster-level event of the kind operators declare and later write up. These have signatures that do not look like a contended pool, and they are confirmed on official status properties rather than deduced from your failures.
  • A local fault. A rate-limited endpoint, a lagging node, a bad network path or a stale blockhash in your own code. All of these produce failures that feel like congestion and are entirely yours.

The reason to keep them separate is that the correct response differs in each case. Reducing size and widening deadlines is right for contention and useless during an incident. Pausing is right during an incident and unnecessarily expensive during ordinary contention on one pair. Rewriting your retry logic is right for a local fault and irrelevant to both.

What you can change on your side

Everything below is inside your control and none of it requires knowing what the rest of the network is doing.

  • Measure the compute your transaction actually consumes by simulating it, then request a limit modestly above that number rather than a round guess.
  • Set the priority price deliberately, from the contention on the accounts you are writing, not from a chain-wide average that describes markets you are not in.
  • Keep the retry window shorter than the blockhash lifetime, so you stop paying attention to attempts that can no longer succeed.
  • Make retries idempotent in intent. If a replacement can execute alongside the original, you have built a double-fill machine rather than a retry.
  • Reduce trade size before raising price. Smaller units contend for less of the per-account allowance and are easier for a scheduler to place.
  • Use address lookup tables for routes with many accounts, so the packaging constraint stops masquerading as congestion.
  • Decide the stopping rule in advance and write it where you will see it, because the decision is worthless if it is made during the session it applies to.

Reading the evidence afterwards

After a contended session, the only account of what happened that is worth anything is the one on chain. Take the signatures you have and look them up in an explorer. A signature that exists tells you the transaction was included and lets you read why it succeeded or failed. A signature with no record tells you it was never included, which is a completely different problem with a completely different fix.

The public Solana block explorer is enough for this and does not require you to trust anyone's dashboard. Work through a handful of representative attempts rather than all of them; the pattern usually appears within five.

What you are looking for is a split. If most attempts were included and failed on chain for a reason like slippage or an insufficient balance, congestion was not your problem and your parameters were. If most attempts have no record at all, you were losing the inclusion competition and the levers in the previous section are the ones to reach for. Those two conclusions lead to opposite changes, which is why guessing between them is expensive.

Traders who run this pass regularly stop describing bad sessions as bad luck. They end up with a short list of settings that have been changed once each, for a stated reason, with a specific observation behind them. That list is worth more than any live indicator, because it survives the next condition instead of describing the last one.

It is also the honest basis for evaluating any automation you rent or build. A Solana volume bot that reports attempts, inclusions and on-chain failures separately is giving you the same split you just produced by hand; one that reports only a success count is asking you to take the interesting part on faith.

Questions the desk keeps being asked

What causes congestion on Solana?

Demand for inclusion in a specific block exceeds what that block can carry. Blocks have published limits on total compute, on compute consumed by writes to any single account, and on the size of an individual transaction. When many participants want the same account in the same slot, the constraint that binds is usually the per-account one rather than the whole-block one, so the chain can look busy in one place and idle everywhere else.

Why does my transaction disappear instead of failing?

Solana has no mempool, so there is no waiting room in which an unincluded transaction sits. Clients forward transactions to the current and upcoming leaders, and a leader that cannot fit your transaction simply does not include it. Once the blockhash you referenced is too old to be accepted, the transaction cannot land at all and nothing on chain records that it ever existed.

Do higher priority fees guarantee inclusion?

No. A priority fee improves your position in the leader scheduler relative to other transactions competing for the same resources, which is a ranking rather than a reservation. If the account you need is saturated for the whole period you are able to keep retrying, a higher price buys you a better place in a competition that still has more entrants than seats.

Is congestion the same thing as the network being down?

No, and conflating them leads to the wrong response. During congestion the chain is producing blocks normally and settling transactions for everyone who wins inclusion. Incident classes that stop or restart block production are different events with different signatures, and they are declared by operators on official status properties rather than inferred from your own failures.

Should I raise my compute unit limit to be safe?

Requesting far more compute than your transaction uses makes it more expensive at any priority price and gives the scheduler a larger block to fit you into. The better habit is to measure what your instruction actually consumes through simulation and request a limit modestly above that figure, which lowers cost and improves your chance of fitting into a partly filled block.

Does congestion affect every venue equally?

Rarely. Because the binding constraint is usually write access to specific accounts, a heavily traded pool can be effectively saturated while other pools on the same chain settle without difficulty. That is why a trader watching one pair and a trader watching another can both be accurate and completely disagree about whether the network is congested.

How long does a congested period last?

This desk does not publish durations, because a duration written today tells you nothing about the period you are in now. What is worth knowing is the shape: contention follows attention, so it tends to build with an event, persist while the event holds interest, and fade unevenly rather than all at once. Your stopping rule matters more than any estimate.

Filed in Conditions by The Network Conditions Desk. Every mechanism on this page is described from public protocol and client documentation; every number is either a published constant or arithmetic labelled as illustrative. How the desk sources and corrects its pages is set out in about the desk.