From 602e27fadb1f3ddcc1f3c38e078ead460669ecd0 Mon Sep 17 00:00:00 2001 From: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:07:05 -0400 Subject: [PATCH] relay: default BUZZ_WRITE_BATCH_MAX to 0 (batching opt-in) Mari's repaired-T1a-base gate at bdbf2f0c1 (release binary, alternated 0/16 restarts, matched accepted counts): batching cuts DB commits/msg ~25% but regresses p50 43-58% and p99 52-74% at 500-1000 QPS. The single global batch lane serializes all channels behind one transaction at a time, which outweighs commit amortization on the repaired base. Ship the machinery opt-in; flip the default only if the lane-serialization cost is fixed and remeasured. Co-authored-by: Dawn (sprout agent) Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> Signed-off-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com> --- crates/buzz-db/src/batch.rs | 4 +++- crates/buzz-relay/src/config.rs | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/buzz-db/src/batch.rs b/crates/buzz-db/src/batch.rs index c1cbdecd8..f6a180f2d 100644 --- a/crates/buzz-db/src/batch.rs +++ b/crates/buzz-db/src/batch.rs @@ -55,7 +55,9 @@ use crate::error::{DbError, Result}; use crate::event::ThreadMetadataParams; use crate::Db; -/// Default maximum events coalesced into one transaction. +/// Suggested maximum events coalesced into one transaction when batching is +/// enabled. Not the relay default — `BUZZ_WRITE_BATCH_MAX` defaults to `0` +/// (batching off); see `Config::from_env` in `buzz-relay`. pub const DEFAULT_MAX_BATCH: usize = 16; /// Queue depth for pending insert requests (matches the relay's default diff --git a/crates/buzz-relay/src/config.rs b/crates/buzz-relay/src/config.rs index abc756dcb..7c398deae 100644 --- a/crates/buzz-relay/src/config.rs +++ b/crates/buzz-relay/src/config.rs @@ -68,7 +68,10 @@ pub struct Config { pub max_concurrent_handlers: usize, /// Maximum plain event inserts coalesced into one group-commit /// transaction (`BUZZ_WRITE_BATCH_MAX`). `0` disables batching and every - /// insert commits individually (the pre-batching behavior). + /// insert commits individually (the pre-batching behavior). Defaults to + /// `0`: benchmarks on the repaired-T1a base showed the single batch lane + /// cuts DB commits/msg ~25% but regresses p50/p99 latency at 500-1000 QPS, + /// so batching is opt-in until that trade-off is resolved. pub write_batch_max: usize, /// Per-connection outbound message buffer size (number of messages). pub send_buffer_size: usize, @@ -433,10 +436,13 @@ impl Config { .and_then(|v| v.parse().ok()) .unwrap_or(1024); + // Default off (`0`): group-commit batching measurably regressed + // p50/p99 latency at 500-1000 QPS on the repaired-T1a base despite + // saving ~25% of DB commits. Opt in explicitly per deployment. let write_batch_max = std::env::var("BUZZ_WRITE_BATCH_MAX") .ok() .and_then(|v| v.parse().ok()) - .unwrap_or(buzz_db::batch::DEFAULT_MAX_BATCH); + .unwrap_or(0); let send_buffer_size = std::env::var("BUZZ_SEND_BUFFER") .ok()