sluice

By Steph9
Scroll to open

sluice

Bounded fan-out for Go. One producer, N workers, and a hard ceiling on how much work is in flight at once. When the ceiling is reached the gate blocks the producer. It does not buffer, it does not drop, and it does not grow. Backpressure reaches your caller instead of your heap.

The Problem It Was Written For

A worker pool with an unbounded channel in front of it is not a worker pool, it is a queue with extra steps. Under load the producer runs ahead, the channel grows, memory climbs, and the process dies holding several minutes of work it was never going to finish in time. The usual fix is a buffered channel with a number in it, chosen once, in a hurry, and never revisited.

Gallery image 1
The gate sits between the producer and the workers. Cap is the only tuning knob.

What Blocking Buys You

If the producer is a HTTP handler, blocking turns into a slow response and then a timeout the client can see and retry. That is a signal. A silently growing buffer is not a signal, it is a delayed outage with no attribution.

When Not To Use It

If your producer cannot tolerate being blocked, this is the wrong library and the README says so in the second paragraph. You want a bounded queue with an explicit drop or spill policy, and that is a different set of trade-offs.

Exported identifiers

6

Runtime dependencies

0

Go versions in CI

1.21 to 1.24

Race detector on every test

yes

Contributors

23

"

We had tuned that buffer size four times in two years. Replacing it with a cap we could actually reason about ended the conversation permanently.

"

from a thread on issue 141

The Pages On This Slate

Quickstart is the twenty minute version, and it is written to be followed rather than skimmed. Contributors names the people who wrote the parts you are about to depend on. Changelog is the honest one: it records what broke, not only what shipped, because the release that broke your build is the release you will come here to read about.