The pattern
A producer writes faster than a consumer can absorb and nothing pushes back: stream write return values ignored, unbounded buffers, limiters scoped to the wrong thing. Load that should have queued politely instead accumulates as memory growth, cardinality explosions, or starvation of neighbors.
( 01 )Symptoms
How this failure announces itself.
- warningA worker's heap grows steadily under load until the process is OOM-killed.
- warningMetric series counts or queue depths spike together with traffic.
- warningOne tenant's burst starves every other tenant of a shared resource.
( 02 )First moves
The first ten minutes — establish facts before touching code.
- 1Capture a heap profile or memory timeline during load and identify what is accumulating.
- 2Find the producer of that accumulation and check whether anything ever tells it to slow down.
- 3Measure consumer throughput against producer rate to size the gap.
- 4Check limiter scope against the failure: who was supposed to be limited and was not?
( 03 )Where to look
The code and config that usually owns this bug.
- searchStream write return values - false means stop until drain, and ignoring it buffers without bound.
- searchDrain handling - does the producer actually pause, or just keep pushing?
- searchLimiter scopes - a global limiter lets one tenant consume the whole budget; a per-call limiter limits nothing.
- searchTelemetry dimensions - backpressure problems often surface first as cardinality growth.
( 04 )Common fixes
Fix the cause, then make the regression impossible.
- buildRespect drain: pause the producer when write returns false and resume on the drain event.
- buildBound every internal buffer and decide explicitly what happens at the bound - block, shed, or sample.
- buildScope shared resources per tenant or key so one consumer cannot starve the rest.
- buildAdd a peak-memory assertion to load tests so regressions fail before production.
( 05 )Prove the fix
A fix you can't demonstrate is a guess. Close the loop.
- verifiedA load test above consumer capacity shows memory plateauing instead of climbing.
- verifiedThe slow-consumer test shows the producer pausing on drain and resuming after.
- verifiedOne tenant's burst no longer degrades another tenant's latency in tests.