Skip to content

Transaction Fees and Local Fee Markets

The previous page pinned down the unit: a lamport is one billionth of a SOL, the integer in which every balance and every fee is actually denominated. This page spends that unit. It answers the most concrete question a user of a global state machine can ask — what does one transaction cost, and who decides? — and then shows how the answer is shaped, end to end, by a design choice you already met: that every Solana transaction declares the accounts it will touch before it runs.

That single fact is why Solana can do something Ethereum structurally cannot: price congestion per account instead of per block. A wildly popular NFT mint can make its own account expensive without raising the price of an unrelated token swap in the same slot. By the end of this page you’ll see that Solana’s fee model isn’t a bolt-on — it’s the economic shadow of Sealevel’s parallel scheduler.

The base fee: fixed, per signature, and boringly cheap

Section titled “The base fee: fixed, per signature, and boringly cheap”

Start with the part that does not move. Every Solana transaction pays a base fee for being included in a block, and that fee is astonishingly simple:

5,000 lamports per signature. Fixed. It does not depend on what the transaction does, how much compute it burns, or how busy the network is.

A signature is an ed25519 signature over the transaction — one per signer. The overwhelmingly common case is a single-signer transaction, so the overwhelmingly common base fee is:

1 signature × 5,000 lamports = 5,000 lamports
= 5,000 / 1,000,000,000 SOL
= 0.000005 SOL

That is the price whether the transaction is a plain lamport transfer, a token swap that touches a dozen accounts, or a program that spends its whole compute budget. The base fee is charged for verifying signatures and including the transaction, not for the work the program does. Two signers cost 10,000 lamports; three cost 15,000; the rule is exactly linear in the signature count.

base_fee = 5,000 lamports × (number of signatures)
1 signer → 5,000 lamports = 0.000005 SOL
2 signers → 10,000 lamports = 0.000010 SOL
3 signers → 15,000 lamports = 0.000015 SOL

Why fix it, and why per signature? Because signature verification is the one cost the runtime pays for every transaction before it can even schedule it — it is the price of admission to the serialization stage that gates the whole pipeline. Pricing that flat and per signature keeps the base cost of using the chain predictable and near-zero, which is exactly what a system built for high throughput wants: the default transaction should be cheap enough that nobody thinks about it.

The priority fee: an optional bid, priced per compute unit

Section titled “The priority fee: an optional bid, priced per compute unit”

The base fee gets you included, eventually. It says nothing about when. When a slot is contested — more transactions want in than fit, or more transactions want to write the same account than can be serialized — inclusion and ordering become scarce, and Solana auctions them off with an optional priority fee (also called a prioritization fee).

A priority fee is not a flat number. It’s a price per compute unit, quoted in micro-lamports (millionths of a lamport), attached via a Compute Budget instruction. You declare two things: how many compute units your transaction may use, and how many micro-lamports you’ll pay for each one. The total priority fee is their product:

priority_fee = (compute units requested) × (price per CU, in micro-lamports)
worked example:
CU limit set = 200,000 CU
price bid = 1,000 micro-lamports per CU
priority_fee (µL) = 200,000 × 1,000 = 200,000,000 micro-lamports
priority_fee (lamports) = 200,000,000 / 1,000,000 = 200 lamports
total fee = base 5,000 + priority 200 = 5,200 lamports ≈ 0.0000052 SOL

Why price it per compute unit rather than as a flat tip? Because compute units are the runtime’s unit of scarce block capacity — a slot holds a bounded number of them. Bidding per CU means a transaction that reserves more of the slot pays proportionally more to jump the queue, and the leader can order pending transactions by the price they’re willing to pay for the capacity they consume. The priority fee turns “who goes first?” into an auction denominated in the exact resource that’s scarce.

base fee : fixed toll to enter (5,000 lamports / signature) — pays for inclusion
priority fee : optional bid for ordering (micro-lamports per CU) — pays for going FIRST

The base fee is permission; the priority fee is priority. In a quiet slot you can skip the priority fee entirely and still land. In a contested slot, it’s how you win.

Local fee markets: contention priced per account, not per block

Section titled “Local fee markets: contention priced per account, not per block”

Here is where Solana’s design pays off, and where it diverges sharply from every single-threaded chain.

Because a transaction declares every account it touches, and because the conflict rule says two transactions collide only when they share a writable account, the runtime knows exactly which account each transaction is contending for. So it can scope the priority-fee auction to that account. This is a local fee market: the price of priority rises only for transactions that write a hot account — everyone else in the same slot is untouched.

Picture a slot during a frantic NFT mint. Thousands of transactions all want to write the same mint account; a few unrelated transactions want to swap tokens on a completely different market:

┌──────────────────────── one slot ────────────────────────┐
│ │
│ writes mint_account ← HOT: thousands contend │
│ tx tx tx tx tx ... ← priority fee here SPIKES │
│ │
│ writes SOL/USDC pool ← cool: a handful of txs │
│ tx tx ← priority fee here stays ~0 │
│ │
│ writes your wallet ← cool: just you │
│ tx ← base fee only, no bidding │
└────────────────────────────────────────────────────────────┘
→ the mint's contention prices ONLY the mint's account.
The swap and the wallet transfer pay their normal, near-zero fee.

The mint’s fee market and the swap’s fee market are different markets in the same block. Bidders for the hot account fight each other for its limited serial throughput — the hot-account ceiling says those writes must serialize, so there’s a real, scarce resource to auction — but that fight is invisible to a transaction touching different accounts. The chain does not have a single congestion price. It has one price per contended account.

Under the hood — the fee market is the shadow of the scheduler

Section titled “Under the hood — the fee market is the shadow of the scheduler”

Local fee markets are not a separate subsystem bolted onto Solana; they’re the direct economic image of the Sealevel scheduler. Trace the chain of reasoning — every link is a design choice you’ve already met:

accounts declared up front (the account model)
contention is per-writable-account (the conflict rule)
the scheduler serializes only the txs that share a hot account
so the SCARCE resource is that account's serial throughput
so the AUCTION for priority is scoped to that account
local fee market: one hot account spikes; the rest of the block is cheap

The reason Solana can price congestion locally is that it knows locally where the contention is — and it knows that only because transactions declare their footprints so the runtime can reason about them before executing. Same declaration, two payoffs: it enables parallel execution, and it enables localized pricing. You cannot have the second without the first. A chain that can’t tell which account a transaction will write can’t build a per-account fee market, because it doesn’t know which accounts are hot until it’s too late.

Contrast with Ethereum: one global base fee for the whole block

Section titled “Contrast with Ethereum: one global base fee for the whole block”

Ethereum prices congestion with EIP-1559: a single base fee per gas that applies to the entire block and adjusts up or down between blocks depending on how full the last block was. There is exactly one base fee at a time, and it is global.

The consequence is the mirror image of Solana’s model. On Ethereum, transactions can’t be run in parallel because a contract holds its own state and the runtime can’t know what a call will touch until it runs it — so there’s one queue, one ordering, one price. When a single popular contract gets hot (a hyped mint, a token launch), demand for that contract drives up the base fee for the whole block — and everyone paying to do anything unrelated in that block pays the elevated price too. One hot contract taxes the entire network.

Ethereum (EIP-1559) Solana (local fee markets)
────────────────── ─────────────────────────
ONE global base fee per block ONE base fee per contended ACCOUNT
set by how full the whole block was set by contention on that account only
hot contract → price rises for EVERYONE hot account → price rises for
in the block (state footprint unknown, transactions writing THAT account
so one queue, one price) (footprint declared, so one market
per account)

Neither is “wrong” — they’re consequences of opposite architectural bets. Ethereum optimizes for a single global ordering, so it prices a single global block. Solana optimizes for throughput via parallelism, so it inherits the ability — and the obligation — to price contention where it actually happens. The fee model is downstream of the execution model.

Where the fee goes: burn and validator, tied back to supply

Section titled “Where the fee goes: burn and validator, tied back to supply”

A fee isn’t just a price; it’s a flow of lamports, and where those lamports go feeds back into the monetary policy of the chain. Solana splits the base fee:

  • A portion is burned — removed from the total supply permanently.
  • The remainder goes to the validator that produced the block (the current leader), as compensation for the work of processing and including the transaction.
base fee (5,000 lamports/sig)
├── burned → supply shrinks by that amount (deflationary pressure)
└── to validator → the leader's reward for inclusion

The burn is the economically interesting half. Every transaction that touches the chain destroys a little SOL, which pushes against the inflationary issuance that funds staking rewards. Fees are therefore not just a user-facing cost — they’re a lever on total supply, coupling network usage to the value of the unit. More activity means more burn; the busier the chain, the more SOL its own use removes from circulation. (Priority fees interact with this split too, and the exact burn fraction has been tuned over time by governance; treat the mechanism — split between burn and validator — as the stable fact, and the precise percentages as a parameter that can change.)

  • Why does it exist? Because a global state machine has to answer two economic questions cheaply and fairly: what does inclusion cost? (the flat base fee) and who goes first when a slot is contested? (the priority-fee auction). Splitting them lets the ordinary transaction stay near-free while scarce ordering still has a price.
  • What problem does it solve? It prices congestion where it happens. Because contention is per writable account, the fee market is per account — so one hot program can’t tax unrelated transactions in the same block, the way a single global base fee would.
  • What are the trade-offs? Users and wallets must estimate a priority fee per compute unit, which is harder than paying one visible global price; misjudge it and you either overpay or get dropped from a contested slot. The base fee’s flatness also means it doesn’t itself throttle demand — the compute budget and per-account limits do that work instead.
  • When should I avoid it? You don’t avoid the base fee — it’s mandatory. You skip the priority fee when the slot isn’t contested: in a quiet moment, bidding for ordering is wasted lamports. Pay it only when you’re competing for a hot account or a full block.
  • What breaks if I remove it? Remove the base fee and there’s no cost to spamming signatures, so the serialization stage drowns and inclusion stops being scarce in a way anyone respects. Remove local fee markets and you’re back to Ethereum’s problem: one hot account would have to raise the price for the entire block, throwing away the whole point of declaring footprints.
  1. What is Solana’s base fee, what is it charged per, and what does a plain single-signer transaction cost in both lamports and SOL — regardless of what the transaction does?
  2. A priority fee is “priced per compute unit in micro-lamports.” Explain what that means, why it’s priced per CU rather than as a flat tip, and how the base fee and priority fee differ in what they buy.
  3. During a hot NFT mint, one account gets thousands of writes while an unrelated token swap sits in the same slot. Explain, from the account declaration onward, why the mint’s contention raises fees only for transactions writing the mint account.
  4. Ethereum’s EIP-1559 has a single global base fee per block. Contrast this with Solana’s local fee markets, and explain why Solana can price per account while Ethereum structurally cannot.
  5. Where do the lamports from a base fee go, and how does that tie the fee system back into SOL’s supply?
Show answers
  1. The base fee is a fixed 5,000 lamports per signature, charged for verifying signatures and including the transaction — not for the work it does. A single-signer transaction therefore costs 5,000 lamports = 0.000005 SOL whether it’s a bare transfer or a compute-heavy swap. Two signers cost 10,000 lamports, and so on, exactly linear in the signature count.
  2. A priority fee is (compute units requested) × (price per CU in micro-lamports) — you declare a CU limit and a per-CU bid, and pay their product (in millionths of a lamport). It’s priced per CU because compute units are the runtime’s unit of scarce block capacity, so bidding per CU makes a transaction pay in proportion to the slot capacity it reserves. The base fee buys inclusion (permission to be in a block); the priority fee buys ordering (going first when the slot is contested) and is optional.
  3. Every transaction declares the accounts it will write up front, and two transactions conflict only when they share a writable account. So the runtime knows the mint transactions all contend for the mint account specifically, and the swap contends for a different account. The scheduler serializes only the mint writers, making that account’s serial throughput the scarce resource — so the priority-fee auction is scoped to the mint account. The swap and any other transaction touching different accounts pay their normal near-zero fee.
  4. Ethereum has one global base fee per block, adjusted by how full the last block was; a hot contract drives that single price up for everyone in the block. Solana has one fee market per contended account, so a hot account’s price spikes only for transactions writing it. Solana can do this because transactions declare their footprints, so the runtime knows which account is hot before executing; Ethereum’s contracts hold their own state, so the runtime can’t know what a call touches until it runs it — leaving one queue, one ordering, one global price.
  5. The base fee is split: a portion is burned (removed from total supply permanently) and the rest goes to the validator that produced the block. The burn couples network usage to supply — every transaction destroys a little SOL, pushing against the inflationary issuance that funds staking rewards — so the busier the chain, the more its own use removes from circulation.