Skip to content

Test your website now

Free, no card. We read only public pages.

Run free audit →

Security

What is rate limiting, and how do you add it to your app?

Rate limiting caps how many requests a client can make in a period. Why login, signup and AI endpoints need it, the common algorithms, and where to enforce it.

Rate limiting caps how many requests a client, such as an IP address, user or API key, can make in a period of time, and answers excess requests with 429 Too Many Requests. It protects login forms from password guessing, signup and contact forms from spam, and expensive endpoints, such as AI features, from abuse and surprise bills.

Published · Last updated

By Michal Měřínský. Audit methodology.

What rate limiting is

A rate limit is a rule such as five login attempts per minute per account, or one hundred API requests per minute per key. Requests over the limit are rejected, usually with status 429 and a Retry-After header, until the window resets.

What needs it most

  • Login and password reset: without limits, attackers can try thousands of passwords per account.
  • Signup, contact and newsletter forms: bots fill them with spam and fake accounts.
  • Endpoints that cost money per call: AI generation, SMS, email sending, image processing. One script can run up a large bill overnight.
  • Search and other expensive queries that can slow the whole app.
  • Public APIs, to share capacity fairly.

An AI feature without a rate limit is an open tap on your API bill. Limit it per user and per IP, and set a spending cap with the AI provider as a backstop.

Common algorithms

  • Fixed window: count requests per clock minute. Simple, but allows bursts at the window edges.
  • Sliding window: count requests in the last sixty seconds at any moment. Smoother.
  • Token bucket: each client gets a bucket that refills steadily, and each request spends a token. Allows short bursts while keeping a steady average.

Where to enforce it

  • At the edge: CDN and WAF rules, such as Cloudflare rate limiting, stop traffic before it reaches your app.
  • In your application or API gateway, where you know the user and can limit per account.
  • With shared storage, such as Redis, when you run more than one instance. In-memory counters reset on deploy and are not shared between servers. Many platforms and libraries provide middleware. A minimal rule in an Express app looks like this:
import rateLimit from "express-rate-limit";
app.use("/api/login", rateLimit({ windowMs: 60_000, limit: 5 }));

Choosing the key

Limit by IP address and by account. IP alone is easy to rotate for attackers and unfair to offices and mobile networks where many people share one address. Account alone does not stop an attacker trying one password against many accounts. Use both for login.

What a scan can and cannot tell you

WebAuditOS checks whether admin interfaces are linked from public pages and autocomplete attributes on password fields inside served-HTML forms, both of which affect how exposed your login is. It does not grade 429 responses as errors, because they usually mean rate limiting is working.

It does not send bursts of requests to test your limits, so it cannot confirm that login, signup or AI endpoints are rate limited. Test that against your own system, carefully.

Rate limiting is invisible from outside until someone hits it. The only proof is a test you run yourself.

Short answers

What status code should a rate limit return? 429, with a Retry-After header.

Does Supabase or Firebase rate limit for me? They limit some auth endpoints. Your own functions and APIs still need limits.

Will rate limiting block Googlebot? Only if your limits are too tight for crawling. Keep them aimed at abuse.

Is a CAPTCHA a rate limit? No, but the two work well together on signup and login.

In the product

The checks this maps to

Every check named here runs on every scan, on every plan - what a plan changes is how many pages are crawled, how long the history is kept and what you can do with the result. These are the ids the findings carry, so you can match a line in a report to the explanation above.