2026-07-03
Every operation has two cost components: fixed overhead (network round-trip, TCP handshake, query parsing, transaction setup) and marginal cost (the actual work per item). When fixed cost dominates, doing one item at a time is wasteful. Batching collects N operations and pays the fixed cost once.
The classic trap is the N+1 query problem. Fetching 500 orders and then querying each order's customer individually is 501 round trips. If your database is 2ms away, that's ~1 second of pure network latency. Batching the customer lookups into one WHERE id IN (...) query drops it to ~4ms — a 250x speedup without changing a single index.
Real-world example: A payments service was writing audit events to Postgres one row at a time — 8,000 rows/second saturating a connection pool. Wrapping writes in a 50ms tumbling window and using COPY for bulk insert dropped CPU by 70% and let a single connection handle 40,000 rows/second. The 50ms added latency was invisible to users; the throughput unlock was massive.
Rule of thumb — the crossover formula:
Three batching triggers, pick based on latency tolerance:
What batching costs you:
Anti-pattern: batching writes to a system that already batches internally (Kafka producers, most SDKs). You're adding latency for savings the client library already gave you. Read the docs before wrapping.
