The op-batcher includes sophisticated throttling mechanisms to manage data availability (DA) backlogs and prevent excessive costs during high-load periods. These mechanisms dynamically adjust block building constraints based on current DA load.
Data availability throttling addresses situations where transaction volume exceeds the DA layer’s throughput capacity. Without throttling, this can lead to:
The throttling system prevents these issues by instructing sequencers to limit block data production when backlogs exceed configured thresholds.
The batcher supports four throttling strategies, each with different response characteristics. The strategies can be understood in this
diagram:

Each strategy responds to the unsafe_da_bytes metric and corresponding thresholds throttle.unsafe-da-bytes-lower/upper-threshold, and results a throttling “intensity” between 0 and 1.
This intensity is then mapped to a maximum tx size and maximum block size to control the miner_setMaxDASize(maxTxSize, maxBlockSize) API calls made to block builders, depending on the configuration variables shown in the diagram above.
When the throttling intensity is zero (the unsafe_da_bytes is less than unsafe-da-bytes-lower-threshold), blocks will continue to be limited at throttle.block-size-upper-limit, whereas transactions are not throttled at all (by using maxTxSize=0).
NOTE Be aware that using
0for eitherthrottle.block-size-lower-limitandthrottle.tx-size-lower-limitresults in no throttling limits being applied (for blocks and transactions respectively).
Behavior: Binary on/off throttling
[!WARNING] If selecting the step controller, you should not rely on default throttling parameters as this could cause too much throttling to be applied too quickly.
Behavior: Linear scaling throttling intensity
Behavior: Quadratic scaling throttling intensity
PID Controller is a control mechanism that automatically adjusts the batcher’s throttling intensity output to maintain a desired load.
Behavior: Proportional-Integral-Derivative control
⚠️ EXPERIMENTAL FEATURE WARNING
The PID controller is experimental and should only be used by users with deep understanding of control theory. Improper configuration can lead to system instability, oscillations, or poor performance. Use at your own risk and only with extensive testing.
The batcher exposes admin RPC endpoints for dynamic throttling control without restarts:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_getThrottleController","params":[],"id":1}' \
http://localhost:8545
Response:
{
"jsonrpc": "2.0",
"result": {
"type": "quadratic",
"threshold": 1000000,
"current_load": 750000,
"intensity": 0.25,
"max_tx_size": 128000,
"max_block_size": 1500000
},
"id": 1
}
Step Controller:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_setThrottleController","params":["step", null],"id":1}' \
http://localhost:8545
Linear Controller:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_setThrottleController","params":["linear", null],"id":1}' \
http://localhost:8545
Quadratic Controller:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_setThrottleController","params":["quadratic", null],"id":1}' \
http://localhost:8545
PID Controller:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_setThrottleController","params":["pid", {"kp": 0.3, "ki": 0.15, "kd": 0.08, "integral_max": 50.0, "output_max": 1.0, "sample_time": "5s"}],"id":1}' \
http://localhost:8545
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_resetThrottleController","params":[],"id":1}' \
http://localhost:8545
The PID controller uses six key parameters:
Core PID Parameters:
kp (Proportional Gain): Controls immediate response to current error
ki (Integral Gain): Controls response to accumulated error over time
kd (Derivative Gain): Controls response to rate of error change
Protection Parameters:
integral_max: Maximum accumulated integral to prevent windupoutput_max: Maximum controller output (typically 1.0)sample_time: Controller update frequency (nanoseconds, e.g., 5000000000 = 5ms)⚠️ EXPERIMENTAL: These profiles are starting points only. Proper tuning requires understanding your specific system characteristics and extensive testing.
Gentle Throttling (Conservative, stable):
{
"kp": 0.1,
"ki": 0.05,
"kd": 0.02,
"integral_max": 1000.0,
"output_max": 1.0,
"sample_time": "10s"
}
Balanced Throttling (Recommended default):
{
"kp": 0.3,
"ki": 0.15,
"kd": 0.08,
"integral_max": 1000.0,
"output_max": 1.0,
"sample_time": "2s"
}
Aggressive Throttling (Fast response, may overshoot):
{
"kp": 0.8,
"ki": 0.4,
"kd": 0.2,
"integral_max": 2000.0,
"output_max": 1.0,
"sample_time": "2s"
}
⚠️ WARNING: PID tuning requires expertise. Improper tuning can cause instability.
Basic Tuning Process:
miner_setMaxDASize RPC calls to configured endpointsThe throttling system communicates with multiple endpoints in parallel:
--l2-eth-rpc--additional-throttling-endpointsEach endpoint runs in its own goroutine with:
The batcher exposes Prometheus metrics for throttling monitoring:
op_batcher_throttle_intensity: Current throttling intensity (0.0-1.0)op_batcher_throttle_pending_bytes: Current pending DA bytesop_batcher_throttle_max_tx_size: Current max transaction size limitop_batcher_throttle_max_block_size: Current max block size limitop_batcher_throttle_controller_type: Current controller typeop_batcher_throttle_pid_error: PID controller error term (PID only)op_batcher_throttle_pid_integral: PID controller integral term (PID only)op_batcher_throttle_pid_derivative: PID controller derivative term (PID only)Use Step Controller when:
Use Linear Controller when:
Use Quadratic Controller when:
Use PID Controller when:
Controller Not Responding:
miner_setMaxDASize method availabilityOscillating Behavior (PID):
Slow Response:
High Error Rates:
Check controller status:
curl -s -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_getThrottleController","params":[],"id":1}' \
http://localhost:8545 | jq
Reset and start fresh:
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_resetThrottleController","params":[],"id":1}' \
http://localhost:8545
Switch to safe mode (step controller):
curl -X POST -H "Content-Type: application/json" \
--data '{"jsonrpc":"2.0","method":"admin_setThrottleController","params":["step", null],"id":1}' \
http://localhost:8545