The Bill That Arrives After the Rollup
You submit a swap on an Optimism-based DEX, pay a few cents, and move on. What you didn't see was the invoice your rollup's sequencer settled ten minutes later: a batch containing your transaction and a few thousand others, posted to Ethereum mainnet. That settlement cost is the real floor beneath every Layer-2 fee. Compress it and every user on the chain gets cheaper. Fail to compress it, and even the cheapest blob slot looks expensive once the chain gets busy.
Calldata compression is one of the least-discussed levers in the L2 fee stack. It predates blobs entirely, it still matters after EIP-4844, and understanding it changes how you read fee announcements from rollup teams.
What Rollups Are Actually Paying For
Before EIP-4844 shipped, rollups posted transaction batches as Ethereum calldata: the raw bytes attached to a smart-contract call. Calldata isn't free. Ethereum's gas schedule prices a zero byte at 4 gas and a non-zero byte at 16 gas. A batch full of addresses, amounts, and signatures is mostly non-zero bytes, so costs added up fast.
EIP-4844 introduced blobs: a separate data lane attached to beacon-chain blocks, priced by a distinct fee market, and automatically pruned after roughly 18 days. Blobs are cheaper than calldata when the blob fee market is quiet, because the target is only three blobs per block (six at the cap, as of the Dencun parameters). But blob fees follow their own supply-and-demand curve. When L2 activity spikes across Optimism, Arbitrum, Base, and zkSync simultaneously, blob fees can climb fast enough that calldata, compressed well, becomes competitive again.
That's the tension. Compression is what resolves it.
The Mechanics of Squeezing Bytes
Rollups apply compression in layers. Think of it like a municipal water system: you reduce pressure loss first by straightening the pipes, then by widening them. Doing only one is leaving efficiency on the table.
The first layer is encoding. A standard Ethereum transaction carries a 20-byte recipient address, a 32-byte value field, a nonce, a gas limit, a gas price, and a signature. Inside a rollup batch, most of that is redundant. The sequencer already knows which chain the transaction is for. Nonces are sequential and can be omitted or delta-encoded, storing the difference from the previous nonce rather than the full number. Addresses that appear repeatedly in a batch get replaced with a short index: instead of repeating a 20-byte contract address 400 times, the batch stores it once and references it with a 2-byte index. In ZK rollups especially, signatures can be aggregated so that one proof covers thousands of transactions instead of one ECDSA signature per transaction.
Here's a concrete case. Take a realistic batch of 1,000 simple ETH transfers. Uncompressed, each might occupy around 100 bytes after basic encoding (address, value, nonce, signature). That's 100,000 bytes raw. After delta-encoding nonces, replacing repeated addresses with indices, and stripping fields the rollup contract already knows from context, you might land at 30 to 40 bytes per transaction. Call it 35,000 bytes.
The second layer is general-purpose compression. Once the batch is semantically encoded, rollups run it through algorithms like zlib or the more modern Brotli. These exploit statistical patterns: repeated byte sequences, common prefixes, low-entropy fields. A batch of Uniswap swaps all calling the same function selector (the first 4 bytes of the calldata) compresses extremely well, because that 4-byte pattern appears thousands of times. Brotli typically achieves 10 to 30% additional reduction on already-encoded rollup batches.
Combined, a well-optimized rollup can post a batch of 1,000 transactions in roughly 10 to 15 bytes per transaction of final on-chain data. At calldata pricing of 16 gas per non-zero byte, that's 160 to 240 gas per transaction, at a time when a plain ETH transfer on L1 costs 21,000 gas. The compression ratio is doing serious work.
The Blob Fee Crossover: When Calldata Wins
Blobs have their own fee unit (blob gas), their own base fee, and their own EIP-1559-style adjustment mechanism. One blob holds 128 KB (131,072 bytes). If a rollup needs to post 50 KB of compressed batch data, it fits in one blob and pays one blob's worth of fee regardless of whether it used 50 KB or 128 KB. Efficient, when fees are low.
Now consider two sequencers, call them Ava and Ben, running different rollup stacks during a period of high L2 activity. Ava's chain uses standard zlib compression and posts via blobs. Ben's chain uses a custom encoding layer plus Brotli, dropping batch size by an extra 40%, and has the flexibility to route data as calldata when blobs are congested.
Ava's batch for 2,000 transactions compresses to 90 KB, requires one blob (it fits under 128 KB), and costs whatever one blob costs that block. Ben's batch for the same 2,000 transactions compresses to 54 KB. If blob fees have spiked because six other rollups are competing for the same six blob slots, Ben's chain can post that 54 KB as calldata and pay roughly 54,000 bytes times 16 gas per non-zero byte: approximately 864,000 gas. At a mainnet base fee of 10 gwei, that's 0.00864 ETH. One blob at the same moment might cost more if the blob base fee has climbed. Ben's users pay less. Not because of any magic, but because his team spent engineering time on encoding.
This crossover isn't theoretical. Rollup teams publish their data-posting strategies, and several have documented fallback logic that monitors both fee markets in real time and chooses the cheaper route per batch.
What the ZK Rollup Stack Does Differently
Optimistic rollups post transaction data so that anyone can reconstruct state and challenge fraud. ZK rollups post a validity proof plus enough data for state reconstruction. The proof itself is typically large (tens to hundreds of kilobytes depending on the proving system), but it replaces individual transaction signatures entirely.
For calldata compression, this matters because signatures are among the least-compressible bytes in a batch. An ECDSA signature is 64 bytes of high-entropy randomness. It doesn't compress. A ZK rollup that aggregates 10,000 transactions into a single proof eliminates 640,000 bytes of signature data from the batch entirely. The remaining data (amounts, addresses, function calls) compresses far better than a mixed batch riddled with uncompressible signatures.
zkSync Era and StarkNet have both published figures showing effective data costs well below 10 bytes per transaction for simple transfers, achieved partly through signature elimination and partly through custom state-diff encoding. Instead of posting every transaction, they post only the net change in each account's balance and nonce. If the same address sent and received five times in one batch, only the final state difference appears on-chain. That's a qualitatively different approach to compression, and it's why ZK rollups consistently quote lower data costs per transaction than optimistic rollups on an apples-to-apples basis. The optimistic camp has real catching-up to do here.
One Caveat Worth Taking Seriously
Compression ratios are not stable. They depend heavily on transaction composition. A batch of identical simple transfers compresses beautifully. A batch of complex DeFi interactions, each calling a different contract with unique calldata, may compress only modestly because entropy is high and patterns are sparse. Rollup teams quoting "X bytes per transaction" are usually citing their best-case workload, and you should read those numbers accordingly.
Blob fee markets are also young. The parameters set at Dencun (target three blobs, max six) will change as Ethereum's roadmap progresses toward higher blob counts. As blob capacity increases, blob fees should fall structurally, which shifts the crossover point and makes the calldata fallback less necessary. Compression still reduces absolute costs, but the competitive dynamics between the two data lanes will look different once blob targets reach dozens per block.
Are you running a rollup or building on one? The actual number to watch is bytes per transaction in your specific workload, not the headline compression ratio from a different chain's press release.
Calldata compression is unglamorous infrastructure work: encoding schemes, lookup tables, algorithm benchmarks. Nobody writes breathless threads about Brotli compression ratios. The teams that obsess over those ratios, though, are the ones whose users notice every single day that their fees are quietly lower than everywhere else. The pipe either moves water or it doesn't.