Why you shouldn’t use Redis as a rate limiter: Part 1 of 2
A tour of the common Redis-based rate limiter implementations — and the correctness and performance traps each one hides.
We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Rate limiting and admission checks that help reduce overload and protect expensive work.
Set admission budgets for launch spikes and promos before excess work reaches your handlers.
Fewer moving parts to run and monitor. Spend less on Redis and ops.
Add via SDK. Keep your stack. Clear limits your customers understand.
UNDERSTAND OVERLOAD · KEEP USEFUL WORK MOVING
For developers, architects, and managers: 27 narrated lessons on why services overload and how to protect them. No cloud experience required. Start with one request, or jump to any lesson.
Four chapters, one learning path. Read or listen in any order. ~41 minutes total · Times shown at 1×.
Keep enough capacity to finish work and recover.
Contain one customer's excess without punishing everyone.
Reduce work entering a shared dependency when it slows.
Choose, combine, and test the right protections.
Read the explanation or use the course map above. Audio is optional.
Recovery capacity and feedback
Only useful end-to-end results establish service.
Do not count desired or booting copies as ready.
Illustrative capacity and request counts, not a deployment recipe. Readiness requires useful results; the traffic-ramp diagram is a decision guide, not measured recovery.
Read the numbered steps in order. The explanation below follows the narration.
A partially restarted fleet has less ready capacity.
Control admission while dependencies, replicas, and caches recover.
Control admission while dependencies, replicas, and caches recover.
Restarting processes is not the same as restoring useful service. In our earlier example, two ready copies could finish two hundred requests per second. Sending the old two hundred forty can overload them before the third copy is ready.
Remember that a cache reuses an answer instead of asking the database again. Suppose, among one hundred requests, a warm cache answers eighty and twenty need one database call each. A cold cache has none of those answers: the same hundred requests now need a hundred database calls. That is five times the database work, without more customers.
Reduce or temporarily stop admitted traffic through a tested control. Keep resource limits active during recovery. Restore required dependencies and ready application copies. Where warming caches helps, bound that work too; warming itself loads the database.
Send a small trial of real work. Check that complete reports arrive, waiting clears, and memory stays bounded. A healthy process alone is not enough. Increase in small steps, observing each step before adding more. If waiting or failures grow, hold or reduce traffic again. A timer or fixed ramp percentage is not proof that capacity has recovered. Recovery order and useful cache preparation depend on the application. Rehearse this with its actual dependencies, instead of assuming every restart can immediately take full traffic.
The application copies return at different times. C is still starting and supplies no ready capacity. Even a running copy also needs working dependencies before it can complete the customer’s report.
Using the earlier equal-cost model, two ready copies provide 200/s while the offered demand is 240/s. A third starting copy adds no ready capacity yet. Actual recovery capacity can be lower while caches or dependencies recover.
A valid cached answer can serve a repeated request without asking the database again. Restart behavior depends on where the cache lives; the following example explicitly considers a cache whose reusable answers are absent.
In this illustration, eighty requests reuse valid answers and twenty each need one database call. Every tile represents ten customer requests, so the C tiles avoid database work and the D tiles require it.
The same 100 customer requests now find no reusable answers. Assuming one database call per miss, every request reaches the database. We did not add customers; we removed the reuse that previously avoided work.
Compare the two cases for the same one hundred requests. Database calls increase fivefold in this simplified example. That does not imply five times the latency, or establish any safe traffic rate for the recovering database.
Use a recovery control that has actually been rehearsed. Reducing or stopping admitted work keeps the recovering system from being immediately overwhelmed by the old demand; the exact mechanism depends on your application.
Do not disable the application’s resource bounds just because it is recovering. Accepted work, cleanup, and refusals still need working space while dependencies and traffic conditions are changing.
Required dependencies must respond and enough application copies must be ready. This is an end-to-end readiness relationship, not a universal process restart order; your dependency structure determines the recovery sequence.
Preparing useful cache entries can reduce later misses, but the preparation itself may query the database. Bound that work against recovering capacity. Some caches remain warm or do not benefit from preparation; warming is not a universal prerequisite.
Follow the highlighted trial step. A real report exercises the useful path through the application and dependencies. The rest of the diagram is a decision guide, not a claim that its success conditions have already been observed.
Check complete reports reaching customers, waiting work clearing, and memory remaining bounded. A health check proving that a process is alive is not enough evidence that its dependencies and real request path can handle the offered work.
A successful trial justifies testing a little more traffic, not jumping to the former full load. Allow meaningful request lifecycles and cleanup to reveal the effect of each change before making another increase.
Follow the alternative branch when waiting or failures grow. Pause the increase or reduce admitted work, then reassess. Capacity changes during recovery, and an earlier successful trial cannot justify blindly continuing the ramp.
An elapsed timer, fixed percentage, or desired replica count is not proof that capacity has recovered. Rehearse admission controls and dependency-specific recovery, including cache behavior and meaningful observation between traffic changes.
Content revision: 07c7dd00db17
Download review copy (27 lessons)The same 100 requests previously needed 20 database calls. With no reusable answers, each needs one call. What changed before adding any customers?
Database calls rose from 20 to 100: five times the work in this illustration. That does not imply five times the latency, or prove that restarting processes restored useful capacity.
Keep admission and resource bounds active; send a small trial, observe complete customer results and retained work, then increase, hold, or reduce traffic based on the observed effect.
Cache preparation and recovery order depend on the application. Do not invent one universal restart procedure.
Start here. No earlier lesson is required.
Bigger buffers buy time. Caching can remove work. Backpressure reduces incoming work.
240 requests/s ÷ 3 = 80 each; after one loss, 240 ÷ 2 = 120 each.
Application-owned local admission protects room to finish work and respond.
Serverless and autoscaling change how compute is supplied, not whether resources are finite.
Database unavailable → calls wait or fail → unbounded retained app work can cause further failure.
Recovery capacity is time-varying. Rehearse cache misses, dependency readiness, caller repeat attempts, routing delays and the cost of warming. Observe each ramp step over meaningful request lifecycles; a timer or desired replica count does not establish recovered capacity.
Original explanation inspired by Fred Hébert and operational references; no endorsement implied.
AI-generated narration: ElevenLabs Eleven v3, Daniel stock voice. Audio streams only when you start listening.
A tour of the common Redis-based rate limiter implementations — and the correctness and performance traps each one hides.
The myth of infinite serverless scale — why adding machines doesn’t fix overload, and what to do instead.