Too Many Req: A Bucket List Guide to Building a Rate Limiter

Too Many Req: A Bucket List Guide to Building a Rate Limiter

2026年8月23日3 次浏览来源:Dev.to阅读原文

Hello, I'm Maneshwar.

I'm building git-lrc, a Micro AI code reviewer that runs on every commit.

It is free and source-available on Github.

Star git-lrc to help devs discover the project.

Do give it a try and share your feedback.

Every serious API will eventually tell you to sit down and be quiet.

Hammer GitHub, Stripe, or AWS a little too eagerly and your requests start bouncing back with a polite but firm .

I always found that fascinating, so let's build the thing that says no.

By the end of this post we'll have designed a rate limiter that actually holds up when you put it in front of real traffic, and I promise to only make a reasonable number of bucket puns along the way.

A rate limiter does one job: it decides how many requests a client is allowed to make in a given window of time.

It protects your system from getting flattened, and it keeps one greedy user from eating everyone else's lunch.

Simple idea.

Surprisingly spicy implementation.

Let's build it up piece by piece, the way you'd actually reason through it in an interview or a design doc.

First, what are we even building?

Before writing a single line, let's agree on what "good" looks like.

Here's my wishlist: Configurable limits.

Something like "100 requests per minute per user." The rules should not be hardcoded, because free users and premium users deserve different amounts of pain.

Honest rejections.

When someone goes over, we return HTTP and include helpful headers telling them how many requests they have left and when the window resets.

No mystery.

Barely-there latency.

This check runs on every single request, so it has to be fast.

Let's aim for under 3ms at P95.

If your rate limiter is slow, congratulations, you built a second bottleneck.

Highly available and shared.

Multiple servers need to agree on the same counts.

More on why that word "shared" is doing a lot of heavy lifting later.

Cool.

Now let's start naive and let reality punch us in the face a few times.

Attempt 1: the fixed window counter The simplest thing that could possibly work is fixed window counting.

Chop time into neat one-minute slices.

Give each user a counter.

Every request bumps the counter by one.

Hit the limit, get rejected, and the counter resets when the next window starts.

Clean.

Readable.

You could explain it to a rubber duck.

So where do we keep this counter?

Where do we put the counter? (this trips people up) Your first instinct might be the database.

Please don't.

We'd be adding a write to the database on every request, which means the thing we built to protect our system is now quietly overloading it.

That is peak "I have brought peace, freedom, and a full table scan." Okay, database is out.

What about keeping counters in memory on the server?

Blazing fast.

Love it.

Except it only works if you have exactly one server, and nobody runs one server.

The moment you scale out, each box keeps its own private counter.

A sneaky user sends 100 requests to Server A and 100 to Server B and walks away with 200 requests per minute while your limit says

100.

Whoops.

What we actually want is somewhere that is memory-fast and shared across every server.

That's Redis.

It's an in-memory data store, it hands us atomic counter primitives like , and it can expire keys automatically so windows reset on their own.

This is why Redis shows up in basically every rate limiter design ever drawn on a whiteboard.

So far so good.

Now let me ruin it.

The fixed window flaw nobody warns you about Fixed windows have a nasty edge case hiding right at the seams.

Picture a limit of 100 requests per minute.

A user fires 100 requests in the last 10 seconds of one minute, then another 100 in the first 10 seconds of the next minute.

Each window is technically within the limit.

Both are 100 or under.

But zoom out and you'll see 200 requests in a 20 second span, which is very much not the spirit of "100 per minute." This happens at every window boundary, and once someone notices the pattern, they will absolutely abuse it.

分享
Baike.dev

baike.dev helps you discover great languages, frameworks, databases, DevOps and cloud-native tools.

Quick links

About

Contribute

Found a great developer tool? Share it with the community.

Submit a tool
© 2026 baike.dev Developer EncyclopediaUpdated daily · Discover great developer tools