![sluice](https://cdn.slatesource.com/6/9/0/690708aa-9ede-4c5b-9846-6ba98dcfef1a.webp)

# sluice

- [Made in Slatesource](https://slatesource.com/@steph/sluice)
- By [Steph](https://slatesource.com/@steph)
- Created on Aug 5, 2026

## sluicesluice

BoundedBounded fan-outfan-out for Go. OneOne producerproducer, N workersworkers, and a hardhard ceilingceiling on how muchmuch workwork is in flightflight at onceonce. When the ceilingceiling is reachedreached the gategate blocksblocks the producerproducer. It does not bufferbuffer, it does not dropdrop, and it does not growgrow. BackpressureBackpressure reachesreaches your callercaller insteadinstead of your heapheap.

## The ProblemProblem It Was WrittenWritten For

A workerworker poolpool with an unboundedunbounded channelchannel in frontfront of it is not a workerworker poolpool, it is a queuequeue with extraextra stepssteps. UnderUnder loadload the producerproducer runsruns aheadahead, the channelchannel growsgrows, memorymemory climbsclimbs, and the processprocess diesdies holdingholding severalseveral minutesminutes of workwork it was nevernever goinggoing to finishfinish in timetime. The usualusual fixfix is a bufferedbuffered channelchannel with a numbernumber in it, chosenchosen onceonce, in a hurryhurry, and nevernever revisitedrevisited.

![Gallery image 1](https://cdn.slatesource.com/6/b/5/6b5e8751-3f82-4fb1-b7f1-a8ece5ee7fb6.webp)

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

## What BlockingBlocking BuysBuys You

If the producerproducer is a HTTPHTTP handlerhandler, blockingblocking turnsturns into a slowslow responseresponse and then a timeouttimeout the clientclient can seesee and retryretry. That is a signalsignal. A silentlysilently growinggrowing bufferbuffer is not a signalsignal, it is a delayeddelayed outageoutage with no attributionattribution.

## When Not To UseUse It

If your producerproducer cannotcannot toleratetolerate being blockedblocked, this is the wrongwrong librarylibrary and the READMEREADME sayssays so in the secondsecond paragraphparagraph. You wantwant a boundedbounded queuequeue with an explicitexplicit dropdrop or spillspill policypolicy, and that is a differentdifferent setset of trade-offstrade-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.

## The PagesPages On This SlateSlate

QuickstartQuickstart is the twentytwenty minuteminute versionversion, and it is writtenwritten to be followedfollowed ratherrather than skimmedskimmed. ContributorsContributors namesnames the peoplepeople who wrotewrote the partsparts you are about to dependdepend on. ChangelogChangelog is the honesthonest oneone: it recordsrecords what brokebroke, not only what shippedshipped, becausebecause the releaserelease that brokebroke your buildbuild is the releaserelease you will comecome herehere to readread about.

[Package reference on pkg.go.dev](https://pkg.go.dev/github.com/tomasleitner/sluice?utm_source=slatesource)

[Source and issue tracker](https://github.com/tomasleitner/sluice?utm_source=slatesource)