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.
Where code runs, what is active, and what remains shared
A report is requested.
Real resources execute the instructions.
Illustrative placements and operation counts, not platform defaults. Readiness, concurrency scope and memory signals depend on the platform. Local memory admission belongs to your application.
Read the numbered steps in order. The explanation below follows the narration.
Compute runs application instructions in several deployment forms.
Serverless and autoscaling change how compute is supplied, not whether resources are finite.
Serverless and autoscaling change how compute is supplied, not whether resources are finite.
Compute is the part of the system that runs application instructions. That work may run in a fixed pool of servers, containers, or a group that adds and removes servers automatically. That last approach is autoscaling. New capacity takes time to become usable, and adding application copies does not necessarily add database capacity.
Serverless means the provider manages the machines and starts your code when needed; it does not mean no machines or no resource limits exist. An execution environment is one place where a copy of that code runs. Each environment has finite resources. Some may be reused, and some may be new.
Concurrency means how many operations are active at the same time. Limiting concurrency can bound how much work remains active inside an environment or against another component. Available controls and memory signals differ between platforms, so one memory-check recipe is not automatically portable.
If application capacity doubles while database capacity stays unchanged, did the whole system double its useful capacity? Not necessarily. The component that cannot keep up still limits the result.
Maya asks for a report. The application is the program; compute supplies the resources that execute its instructions. Receiving a message is not the same as doing that work.
The two panels are alternative placements, not a chain of calls. A server pool has separate machines running application copies. Containers provide separate places for programs on a host; they do not remove the host’s resource limits.
Requests reach A and B. C has been requested, but it contributes no ready capacity yet. Count the copies that can serve now—not the number you asked the platform to create.
C is initializing. A and B still handle the incoming work; C has no incoming request path yet. Adding a desired copy does not instantly relieve the existing servers.
Now suppose C is ready too. All three application copies call the same database. The database is a separate resource: adding an application copy does not automatically add capacity there.
Your code still runs on machines, inside the provider-managed boundary. The provider starts that code when needed. The word serverless does not mean machines or finite resources have disappeared.
A and B are separate execution environments inside the managed infrastructure. Each box is a place for a copy of your application code, not an unlimited shared machine.
Provider-managed execution still has a resource budget. Each environment can run out of its available memory. The strips illustrate finite budgets, not byte measurements or platform defaults.
The next invocation may reuse environment A, where code has run before, or start in a new environment B. These are alternatives—not two calls made by the application. Never rely on getting A again.
Follow the vertical Now line. A, B and C have all started and none has finished: concurrency is three. The earlier completed operation no longer counts. Concurrency measures overlapping work, not requests per second.
Choose an illustrative limit of three in this scope. A, B and C are still active, so D cannot start yet. Decide what to do with excess work; moving it to an unbounded waiting area would not solve the resource problem.
An application-scoped limit covers work in one environment. Protecting a shared dependency also requires reasoning about all its callers. Platforms expose different memory signals and controls; one server middleware recipe is not automatically portable to every serverless runtime.
A and B were already present; C and D are added. All four paths converge on the same database. We doubled the equal-sized application fleet, not the capacity of every component it depends on.
If the database already limits completions, more callers do not necessarily produce more reports. They can simply send more work to the same bottleneck. Check the entire request path before treating added compute as added useful capacity.
Content revision: 07c7dd00db17
Download review copy (27 lessons)Can adding app servers overload a database that did not grow?
Yes. More callers can send more work into the same finite database capacity.
Use signals and concurrency/admission controls actually available in the selected runtime and platform.
Do not assume identical per-request memory observability or middleware support across serverless platforms.
Start here. No earlier lesson is required.
Waiting work can retain memory. A failed allocation or terminated process can stop service.
240 requests/s ÷ 3 = 80 each; after one loss, 240 ÷ 2 = 120 each.
Application-owned local admission protects room to finish work and respond.
Measure ready capacity and per-environment limits separately from desired fleet size. Provider limits and application-owned admission have different scopes.
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.