Throttling
Limiting the rate at which messages or requests are processed to avoid overwhelming downstream services.
Throttling is the practice of limiting how fast your system processes messages or handles requests. Instead of consuming as fast as possible, you set a maximum rate. This protects downstream services from being overwhelmed.
In message-driven systems, a burst of events can easily overload a database, an external API, or another service that wasn't designed for sudden spikes. Throttling gives you a straightforward way to smooth out those spikes.
The typical approach is a middleware that introduces a delay between processed messages. You set a duration, and it ensures at least that much time passes between handling consecutive messages.
Throttling is different from a circuit breaker, though they solve related problems. A circuit breaker stops calling a failing service to give it time to recover. Throttling limits the rate proactively, before anything fails. In practice, you might use both: throttling to keep the baseline load reasonable, and a circuit breaker as a safety net when things go wrong.
There are trade-offs. Throttling increases overall processing latency. If you set the rate too low, messages pile up in the message broker. If you set it too high, you're not protecting much. The right rate depends on what your downstream services can handle, so you'll need to measure.
One common mistake is throttling at the wrong layer. Limiting the HTTP endpoint doesn't help if the bottleneck is an async handler overwhelming a shared database. Think about where the pressure actually comes from and throttle there.
Throttling is one of the simplest reliability patterns to implement, and it's often the first thing worth trying when you see timeouts or degraded performance under load.
References
- Introducing Watermill - Go event-driven applications library — Lists throttling as one of the key functionalities for message-driven applications, alongside metrics, distributed tracing, poison queues, and retrying. Shows how all of these are implemented as handler middlewares in Watermill.
- Watermill 1.3 released, an open-source event-driven Go library — Mentions the Throttle middleware alongside the new CircuitBreaker middleware. Both help avoid overloading downstream services, with Throttle limiting the processing rate and CircuitBreaker stopping calls to failing services.
- Watermill Throttle Middleware Documentation