:INFO [align:center] 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. | :INFO 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 | :INFO.half 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. | :INFO.half 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. | :STATS | :QUOTE [quotetype:plain, subtitle:from a thread on issue 141] 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. | :INFO 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. | :LINK https://pkg.go.dev/github.com/tomasleitner/sluice Package reference on pkg.go.dev | :LINK https://github.com/tomasleitner/sluice Source and issue tracker