Conversation
The flashblock scheduler generates `target_flashblocks = block_time / interval`
trigger times, with the last one firing at `slot_end - end_buffer_ms`. With
the default `end_buffer_ms=0`, the final flashblock fires at the slot deadline
itself and almost always fails to publish before `getPayload` — so the
scheduler allocates a slot that is silently dropped, leaving N-1 usable
flashblocks per block instead of N.
Benchmarked on a 2s chain block with the default 250ms interval (8 flashblocks/
block), 100 agents at 100M gas for 120s:
end_buffer_ms | p95 backrun_sent→landed | idx=8 utilized | landed/120s
---------------+-------------------------+----------------+-------------
0 | 482 ms | no | 34,686
50 | 482 ms | no | 35,976
100 | 331 ms (-31%) | yes | 40,936
150 | 381 ms | yes | 39,393
50ms is not enough buffer for the build/publish; 100ms is the smallest value
in {50,100,150} that lets idx=8 publish before the slot deadline. Larger
values (150ms+) don't help because the extra buffer becomes a larger
end-of-block dead zone that forces more bundles into the next block.
100ms of buffer costs ~5% of the final slot's bundle-intake window (100ms of
2000ms) in exchange for the entire slot being usable. Net effect: 31% lower
p95 landing latency and 18% higher per-block throughput.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Updates the default flashblocks “end buffer” so the final scheduled flashblock is built/published slightly before slot end, avoiding the last slot being effectively unusable under typical timing constraints.
Changes:
- Change
FlashblocksConfigdefaultend_buffer_msfrom0to100. - Change CLI flag
--flashblocks.end-buffer-msdefault from0to100and expand its help text to explain the rationale.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
crates/op-rbuilder/src/builder/config.rs |
Updates runtime default flashblocks config to use a 100ms end buffer. |
crates/op-rbuilder/src/args/op.rs |
Updates the CLI/env default for end buffer to 100ms and documents the behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #[arg( | ||
| long = "flashblocks.end-buffer-ms", | ||
| env = "FLASHBLOCK_END_BUFFER_MS", | ||
| default_value = "0" | ||
| default_value = "100" | ||
| )] | ||
| pub flashblocks_end_buffer_ms: u64, |
There was a problem hiding this comment.
This changes the default behavior of a user-facing CLI/config option (from 0ms to 100ms). Please add a note to the crate changelog/release notes so operators who rely on the prior default know they may need to explicitly set --flashblocks.end-buffer-ms=0 to preserve old behavior.
|
This doesn't need to be a default though right? We don't use 0 either for running the builder but we don't want to expose what value we're using since adversaries would then know by how much they'd need to degrade building. Also, with continuous building (#458) I think |
|
@akundaz yeah, if the value used in prod isn't 0 then that should be fine, i'll re-bench with continuous building also then |
📝 Summary
The flashblock scheduler generates
target_flashblocks = block_time / intervaltrigger times, with the last one firing atslot_end - end_buffer_ms. With the defaultend_buffer_ms=0, the final flashblock fires at the slot deadline itself and almost always fails to publish beforegetPayload— so the scheduler allocates a slot that is silently dropped, leaving N-1 usable flashblocks per block instead of N.Benchmarked on a 2s chain block with the default 250ms interval (8 flashblocks/ block), 100 agents at 100M gas for 120s:
end_buffer_ms | p95 backrun_sent→landed | idx=8 utilized | landed/120s
---------------+-------------------------+----------------+-------------
0 | 482 ms | no | 34,686
50 | 482 ms | no | 35,976
100 | 331 ms (-31%) | yes | 40,936
150 | 381 ms | yes | 39,393
50ms is not enough buffer for the build/publish; 100ms is the smallest value in {50,100,150} that lets idx=8 publish before the slot deadline. Larger values (150ms+) don't help because the extra buffer becomes a larger end-of-block dead zone that forces more bundles into the next block.
100ms of buffer costs ~5% of the final slot's bundle-intake window (100ms of 2000ms) in exchange for the entire slot being usable. Net effect: 31% lower p95 landing latency and 18% higher per-block throughput.
💡 Motivation and Context
Improves signal-boost backrun tail latencies.
✅ I have completed the following steps:
make lintmake test