Skip to main content
This guide takes a chain operator whose largest onchain operating cost is L1 data posting and walks the whole cost loop in one pass: what the batcher spends, the settings that control that spend, and the fee parameters that recover it from users. It involves the op-batcher, your chain’s SystemConfig fee parameters, and, for throttling, the sequencer’s execution client.

Is this guide for you?

Use this guide if:
  • You operate an OP Stack chain: you control the op-batcher deployment and can reach the SystemConfig owner when a parameter change needs it.
  • Your goal is economic (L1 posting costs look too high, or user fees aren’t covering them) rather than a batcher outage or sync problem.
If you are standing up a batcher for the first time, follow the batcher setup tutorial first. If you want to understand how fees work rather than change them, read Transaction fees. If you are evaluating alternative data availability layers, see the Alt-DA mode guide. This guide covers Ethereum DA (calldata and blobs) only.

Before you start

You should already have:
  • A running op-batcher posting batches for your chain, and the ability to change its flags or environment variables and restart it.
  • Access to the batch submitter’s L1 spend history (its address on an L1 explorer) so you can measure the effect of changes.
  • Batcher metrics scraped somewhere you can query; see chain monitoring options.
  • For Step 5, transaction access as the SystemConfig owner (fee scalars are set on L1).

Step 1: Map where the fees go

Two fee flows matter, and they are tuned by different knobs: the fees you pay L1 to post data (batcher settings), and the fees users pay you (SystemConfig fee parameters). Read Transaction fees and take away:
  • The three components of a user fee (execution gas fee, L1 data fee, operator fee), and that the L1 data fee is the component that exists to recover your batcher spend.
  • Which scalars price the L1 data fee (basefeeScalar and blobBaseFeeScalar); you will set them in Step 5.
Then skim Transaction Fees 101 and take away which fee parameters are operator-adjustable and the example scenarios that match your chain’s traffic pattern.

Step 2: Balance your sequencing-window budget

Cost tuning trades posting cost against batch-submission speed, and the sequencing window puts a hard cap on that trade. The faster you submit batches, the sooner your users’ transactions get Ethereum finality guarantees; the longer you accumulate before posting, the cheaper each byte gets, up to the cap. Read the batcher policy section of the batcher configuration guide and take away:
  • Your chain’s sequencing window, which is 3,600 L1 blocks (12 hours) on standard chains, and that batches must always land on L1 inside it. Breached sequencing windows result in a 12 hour reorg.
  • The standard requirement to target batch submission at 1,800 L1 blocks (6 hours) or lower, and why operators leave a congestion buffer below that.
  • That a long submission interval stalls the safe head for up to that interval, which delays exchanges and bridges that wait for Ethereum finality.
Every choice in Steps 3 and 4 must keep batch submission inside the sequencing window. Decide now how long your chain’s users can wait for Ethereum finality; that number, not the 12-hour hard cap, is your real budget.

Step 3: Choose a data availability type

The batcher posts to Ethereum as calldata or as blobs, controlled by --data-availability-type (OP_BATCHER_DATA_AVAILABILITY_TYPE); valid values are calldata (the flag’s default), blobs, and auto. A blob must be bought whole, about 130 KB of usable capacity, whether or not you fill it. In practice that rarely favors calldata: outside short demand spikes, the blob base fee has sat at or near its floor since blobs launched, so even a partly filled blob usually costs less than posting the same bytes as calldata, and L1’s Pectra upgrade (EIP-7623) raised calldata pricing for data-heavy transactions on top of that. To check which market is cheaper right now, compare the current blob base fee with the L1 base fee on any gas tracker that shows both, or let auto make the comparison per channel. To execute a switch, follow Using Blobs, which covers switching to blobs, switching back to calldata, and auto mode; take away that a DA-type switch also changes the correct scalar values, so plan Step 5 in the same change window.

Step 4: Size your channels

With the DA type fixed, the biggest cost levers are how long the batcher accumulates data before posting and, on blobs, how many blobs it packs per transaction:
  • --max-channel-duration (OP_BATCHER_MAX_CHANNEL_DURATION), in L1 blocks. The default is 0 (duration tracking disabled). Read the channel duration recommendation and take away the recommended 1,500-block (5-hour) ceiling, the reasons not to exceed it, and that a full channel is posted early regardless of this setting.
  • --target-num-frames (OP_BATCHER_TARGET_NUM_FRAMES), the number of frames (and so blobs per blob transaction) to target. The default is 1. Read the multi-blob recommendation and take away the companion transaction-manager settings a multi-blob configuration needs and the blob-congestion caveat.
  • --batch-type=1 (OP_BATCHER_BATCH_TYPE) enables span batches, which cut batch overhead; the default is 0 (singular). Follow Enable span batches, which includes confirming the Delta upgrade is active first.
The connective logic: To get a concrete blob count, estimate the compressed batch data your chain produces per channel duration and divide by blob capacity (~130 KB); Step 7’s utilization metrics will confirm or correct the estimate.

Step 5: Recover the spend with fee scalars

Posting cheaply is half the loop; the L1 data fee your users pay must track what you now actually spend. Follow the L1 fee section of Transaction Fees 101 to read and set basefeeScalar and blobBaseFeeScalar on your SystemConfig, and take away the direction of each adjustment. For the formula the scalars feed and the values OP Mainnet runs, see the fee parameters reference. Size the scalars against your measured batcher spend so they recover it plus your target margin. If you switched DA type in Step 3, set the new scalars in the same maintenance window: blob-appropriate scalars under calldata (or the reverse) misprice every user transaction until corrected.

Step 6: Decide your throttling posture

Throttling is the batcher’s defense against traffic spikes outrunning your DA budget: when its backlog of un-posted data grows past a threshold, it instructs the sequencer’s execution client (via the miner_setMaxDASize RPC) to limit DA-heavy transactions and blocks. It is on by default, so this step is about checking the defaults fit your cost posture rather than turning something on. Read the batcher sequencer throttling section and take away:
  • The requirement that the sequencer’s execution client exposes the miner RPC namespace, and the follow-the-sequencer caveat for multi-node setups.
  • The default backlog thresholds at which throttling engages and reaches maximum intensity (--throttle.unsafe-da-bytes-lower/upper-threshold), and that the default controller is quadratic (--throttle.controller-type; the options are step, linear, quadratic, and pid).
The decision this guide adds: leave throttling on unless, during traffic spikes, you accept unbounded backlog growth and the cost exposure that comes with posting that backlog at whatever L1 happens to charge. To accept that trade anyway, disable throttling by setting --throttle.unsafe-da-bytes-lower-threshold=0. For controller selection and tuning depth, use the throttling deep dive in the next steps.

Step 7: Verify the outcome

Give a change at least a few full channel cycles, then check both sides of the loop. The batcher exports Prometheus metrics under the op_batcher_<procname> namespace (op_batcher_default_* unless you set a custom process name):
  • Blob utilization (blobs only): the blob_used_bytes histogram should sit near blob capacity (~130 KB). Persistently part-empty blobs mean your channel duration or frame count is oversized for your throughput; revisit Step 4.
  • Posting cadence: batcher transactions from your batch submitter address should appear on L1 at roughly the interval you chose, and never approach the sequencing-window deadline from Step 2.
  • Throttling at rest: throttle_intensity should be 0 and unsafe_da_bytes below the lower threshold in normal operation. If throttling engages routinely, your chain’s steady-state throughput exceeds your posting budget; revisit Steps 3 and 4 before touching Step 6’s thresholds.
  • The economic bottom line: over a representative window, compare the batch submitter’s L1 spend against L1-fee revenue arriving in your fee vaults. A healthy result is revenue at or above spend by your target margin; if not, revisit Step 5.

Next steps

  • Batcher configuration reference: the full flag and environment-variable catalogue. Hand-pinned to op-batcher/v1.10.0 as of 2026-07-16; confirm values against op-batcher --help for the release you run.
  • op-batcher throttling deep dive: the only in-depth documentation of the four throttling controllers, their runtime-management RPCs, and the experimental PID controller’s tuning profiles. In-repo document on develop, as of 2026-07-16.
  • op-batcher readme: batcher architecture and operational detail beyond configuration. In-repo document on develop, as of 2026-07-16.
  • Frame format in the derivation spec: the normative definition of channels and frames, for when you need to reason about what a channel actually contains.