Skip to content

feat(sequencer): dynamic batch production#2291

Merged
Mirko-von-Leipzig merged 6 commits into
nextfrom
mirko/dynamic-batches
Jun 30, 2026
Merged

feat(sequencer): dynamic batch production#2291
Mirko-von-Leipzig merged 6 commits into
nextfrom
mirko/dynamic-batches

Conversation

@Mirko-von-Leipzig

@Mirko-von-Leipzig Mirko-von-Leipzig commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR changes batch production from a fixed interval, to producing as many full batches as possible. The current batch.interval: Duration CLI is instead now used to configure the time after which a non-full batch will be scheduled if no full batch can be produced.

The new algorithm is essentially:

  • Whenever a batch completes, attempt to build a full batch if possible.
  • If no batch has been produced for batch.interval seconds, attempt to build a batch of any size.
  • If idle, check for full batches every block.interval / 10 seconds.

In addition, I've removed the failure injection we had in place for batch and block production. These have actually never been used, so they're not really worth the LoC.

Closes #2287

Changelog

[[entry]]
scope       = "node"
impact      = "changed"
description = "Batch production is now dynamic, creating full batches as often as possible, while maintaining a minimum batch rate"

@Mirko-von-Leipzig Mirko-von-Leipzig marked this pull request as ready for review June 28, 2026 11:37
@Mirko-von-Leipzig

Copy link
Copy Markdown
Collaborator Author

Note that the batch selection process is now quite unoptimized. This will be improved as a separate PR.

Comment thread crates/block-producer/src/batch_builder/mod.rs Outdated
Comment thread crates/block-producer/src/batch_builder/mod.rs
Comment thread bin/node/src/commands/block_producer.rs Outdated
Comment thread crates/block-producer/src/mempool/graph/transaction.rs Outdated
Comment on lines 239 to 247
if selected.is_empty() {
return None;
BatchSelection::Empty
} else if budget.is_exhausted() {
// The selected transactions may exactly consume the budget without another candidate
// being available to trigger the "would exceed" branch above.
BatchSelection::Full(selected.build())
} else {
BatchSelection::Partial(selected.build())
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still slightly suboptimal.

If the budget is not exhausted but all remaining transactions would make the selection go over the budget budget.is_exhausted() will be false and we're returning BatchSelection::Partial here. That in turn makes the scheduler wait for the partial-batch timeout.

If we were to return BatchSelection::Full instead then we could immediately create this batch and then continue with the rest of the candidates.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did debate back and forth on this. But perhaps I settled on the wrong conclusion.

At the moment this only really matters if we have transactions with massive amounts of notes (since the tx count restriction is more binary).

As an example, if we have two extreme txs each with close to the maximum number of output notes, then each batch can only contain one of these. But you could in theory squeeze additional smaller txs in if they arrive.

So I guess the question is, do we want to wait, or do we want to process these asap even if better opportunities might arrive.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really just depends on whether we're optimizing for latency or for throughput.

I think that in most cases it's latency that matters (better UX, as transactions get included faster). But maybe even that is a premature optimization at this point -- I'm fairly sure the block builder will need quite a few tweaks once these decisions start to matter...

@kkovaacs kkovaacs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Mirko-von-Leipzig Mirko-von-Leipzig enabled auto-merge (squash) June 30, 2026 14:32
@Mirko-von-Leipzig Mirko-von-Leipzig merged commit 327d226 into next Jun 30, 2026
24 checks passed
@Mirko-von-Leipzig Mirko-von-Leipzig deleted the mirko/dynamic-batches branch June 30, 2026 14:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Batch production should be dynamic

2 participants