← Back to blog
Security· August 27, 2026 ·7 min read

Rate limiting explained: protect your API without blocking real users

Rate limiting stops one bad actor — or one buggy script — from hammering your site into the ground, without slamming the door on everyone else. Choosing the limits is the hard part.

Mads Edelskjold
Mads Edelskjold
Founder, NordicCDN · ex-datacenter CTO
Rate limiting explained: protect your API without blocking real users
The short version

Rate limiting caps how many requests a client can make in a window of time. It protects login forms, search and APIs from brute force, scraping and runaway scripts. The mechanism is easy; picking limits that stop attackers without catching real people is the part that takes thought — particularly because whole offices and mobile networks share a single IP address.

Every site has a few endpoints that attract trouble. The login form, the password reset, the search box, the public API. Left unguarded, one script can hit them thousands of times a second — guessing passwords, scraping the catalogue, or just malfunctioning enthusiastically because someone forgot a break statement.

Rate limiting is the cap that says "that is enough". The idea takes one sentence; getting it right takes a little more.

The idea

Allow each client a reasonable number of requests per unit of time, and reject or slow the ones that exceed it. A person clicking around a site makes perhaps ten requests a minute. A brute-force script makes thousands. There is an enormous amount of room between those two numbers, which is what makes this work at all.

Real visitor
~10/min
Aggressive bot
thousands/min

Which algorithm, and why it matters

There are three common approaches and the difference between them is more practical than it sounds.

Fixed window

Count requests per calendar minute; reset the counter at the top of each minute. Simple, cheap, and it has an obvious flaw: a client can make its full allowance at 10:00:59 and its full allowance again at 10:01:00, delivering double the intended rate in a two-second burst. Fine for rough protection, not for anything you care about.

Sliding window

Count requests in the trailing sixty seconds rather than the current calendar minute. This closes the boundary hole and is what most people actually want when they say "100 requests per minute".

Token bucket

Picture a bucket holding 60 tokens that refills at one per second. Every request spends a token. Requests at a sane pace never drain it; a burst can spend several at once, and sustained flooding empties it and gets refused until it refills.

bucket of tokens refills steadily → each request spends one empty → slow down
Bursts are tolerated; sustained flooding drains the bucket and gets throttled.

Token bucket is usually the right default, because it matches how real usage actually looks. A person loading a page fires a dozen requests at once and then does nothing for thirty seconds. A strict per-second limit punishes that entirely normal behaviour; a bucket absorbs it.

Choosing the limits

The mistake is one global limit applied everywhere. Your endpoints have wildly different risk profiles and wildly different legitimate usage patterns, so they want wildly different numbers.

EndpointStarting pointOn exceed
Login, password reset5–10 per minute per IPChallenge, then block
Signup, contact form3–5 per minute per IPChallenge
Search20–30 per minute per IPThrottle
Public API, unauthenticated60 per minute per IP429 with Retry-After
Public API, per API keyPer your plan tiers429 with Retry-After
General page browsing300+ per minute per IPThrottle

Those are starting points, not recommendations for your site — the right numbers come from looking at your own traffic. Take a week of logs, find the 99th percentile request rate for real sessions on each endpoint, and set the limit meaningfully above it. If your busiest genuine user does 40 searches a minute, a limit of 30 is going to generate angry emails.

The shared-IP trap

This is the one that catches people, and it catches them in a way that is invisible from your side.

A single IP address is very often not a single person. An office of 200 people behind one NAT gateway is one IP. A university campus is one IP. Mobile carriers routinely put thousands of subscribers behind carrier-grade NAT, sharing a handful of addresses. Corporate VPNs concentrate an entire company onto one exit node.

Set an aggressive per-IP limit and you are not blocking one abusive user, you are blocking everyone at that company, and they experience it as "your website is broken" rather than "we have been rate limited". They will not email you. They will just leave.

Where you can, rate limit on something more specific than an IP — an API key, a session, a user account. For unauthenticated traffic where the IP is all you have, prefer a challenge over a hard block when the limit trips. A shared office passes the challenge and continues; a script does not.

Failing politely

When you do reject a request, do it in the way the standards expect, because the client on the other end may well be a legitimate integration that will behave correctly if you tell it how.

Return 429 Too Many Requests — not 403, which means "you are not allowed", a different and unrecoverable message. Include a Retry-After header saying how long to wait. If you run a public API, send the current limit state on every response, not just the rejections, so a well-written client can slow down before it hits the wall rather than after.

And keep your rate limit responses cheap. If rejecting a request costs you a database query, a determined attacker can still exhaust you using nothing but rejections. This is another argument for limiting at the edge, where the rejection happens before your application is involved at all.

Things worth exempting

  • Verified search crawlers. Googlebot crawls in bursts, and rate limiting it can quietly damage your indexing. Verify and exempt.
  • Your own monitoring. Uptime checks from a fixed address should not be competing with your limits.
  • Webhook senders. Payment providers retry aggressively by design; a limit that blocks them can lose you orders.
  • Static assets. One page view is dozens of asset requests. Limiting them per IP catches normal browsing immediately.

Frequently asked questions

What is rate limiting?

Rate limiting caps how many requests a single client may make within a period of time, rejecting or slowing anything beyond that. It protects login forms, search endpoints and APIs from brute-force attempts, scraping and misbehaving scripts, while leaving normal usage untouched because legitimate traffic sits far below the threshold an attacker needs.

What is a good rate limit for an API?

It depends on the endpoint rather than the site. Login and password reset endpoints justify 5 to 10 requests per minute per IP, signup forms 3 to 5, search 20 to 30, and an unauthenticated public API around 60. Derive your actual numbers from your own logs by finding the 99th percentile request rate of genuine sessions and setting the limit comfortably above it.

What HTTP status code should a rate limit return?

429 Too Many Requests, accompanied by a Retry-After header indicating how long the client should wait. Do not use 403 Forbidden, which signals that the client is not permitted at all rather than that it should slow down and retry. Public APIs should also return current limit state on successful responses so clients can throttle before being rejected.

Why does rate limiting block real users?

Almost always because many people share one IP address. Offices behind a NAT gateway, university campuses, corporate VPNs and mobile carriers using carrier-grade NAT can put hundreds or thousands of genuine users behind a single address. A per-IP limit tuned for one person therefore blocks all of them. Limit on an API key, session or account where possible, and prefer a challenge over a hard block otherwise.

What is the token bucket algorithm?

Token bucket models a bucket holding a fixed number of tokens that refills at a steady rate. Each request consumes one token, and requests are rejected when the bucket is empty. This tolerates short bursts, which is how real browsing behaves, while still capping sustained request rates — making it a better fit for web traffic than a strict fixed-window counter.

Rate limiting is one of those controls where the default configuration is rarely right and the correct configuration is sitting in your access logs. Spend an hour with a week of traffic before you pick your numbers, and you will avoid the far longer afternoon of working out why a customer's entire office cannot log in.

#rate limiting #api #security #abuse
Put it into practice

See how NordicCDN does this for your site:

Mads Edelskjold
Written by
Mads Edelskjold — Founder, NordicCDN · ex-datacenter CTO

Mads has worked in IT — mostly hosting — since he was 16. He took an early stake in a SaaS company and helped grow it through to its acquisition by Visma, has built and run data-center networks, and served as CTO of a Danish data center. He started NordicCDN to make fast, secure infrastructure simple to use.

Make your site load instantly

Start free in two minutes — no card required.

Start free