Rate Limiting & API Throttling Services

Rate limiting decides how much traffic one client, API key or tenant may send before your application starts refusing the excess. Without that control, a script, a leaked key or a noisy integration can exhaust the database, inflate the hosting bill and lock real customers out of login or checkout.

CodeWiz puts those controls in place for public APIs, SaaS products, online stores and websites that already take real traffic. We set them at the edge, in the API gateway and inside the application, key them to the right identity, and add responses, metrics and alerts so a 429 is a deliberate decision. This page is the delivery work. The algorithms are in our complete guide to API rate limiting, and Express middleware is in the Node.js and Express rate limiting article.

It is for teams whose login, search, checkout or public API is being scraped, stuffed with credentials, or growing past a single shared counter. Limits that live in process memory and vanish on deploy are already working against you.

Rate: Chain-link fence in front of blurred red and blue city traffic lights at night

Request Throttling: Rate Limiting That Matches the Endpoint

Request throttling caps how often a caller may hit one action. A password check, a product search and a webhook do not share a budget. We set a limit per route, choose who the counter belongs to, and define “too many” for that action.

What we limit, and on which key

  • Login, OTP and password reset are limited tightly per account and per IP, because these routes are the usual target of credential stuffing and inbox bombing.
  • Search, filters and exports are limited per user or API key, because each call can be expensive even when the caller is legitimate.
  • Checkout and payment attempts stay generous for a real buyer and strict for repeated failures, so a card retry does not look like an attack and an attack does not look like a customer.
  • Public and partner APIs are limited per key, with a separate ceiling for unauthenticated traffic.
  • Webhooks you receive from payment providers and couriers are allow-listed and verified, not thrown into the same bucket as anonymous browsers.

Behind Cloudflare the socket address is the proxy, so an IP limit either blocks everyone or blocks no one. We trust the documented client-IP header only from proxies we operate, never a header the caller can set themselves.

A small edge example

On Nginx, a login route can reject bursts before PHP or Node.js even starts. This is a sketch, not a complete policy:

limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; limit_req_status 429; server { location /login { limit_req zone=login burst=10 nodelay; proxy_pass http://app; } }

The Nginx limit_req module is enough for one server. With more than one instance the counter moves to Redis or to the edge, otherwise each process enforces a different number. Framework libraries differ; we keep those details in the Express article so this page stays on the service.

DDoS Protection Before Traffic Reaches Your Origin

DDoS protection and per-route throttling solve related problems at different layers. A volumetric flood tries to fill the pipe. An application flood sends cheap HTTP requests that are individually valid and collectively ruinous: search, login, add-to-cart, uncached pages. A limit inside your app never sees the first kind, and a network filter often ignores the second.

Cloudflare sits in front of the origin and absorbs volumetric traffic. Request-limit rules, WAF custom rules and bot scores stop repetitive abuse before it consumes PHP workers, Node.js processes or database connections. Our Cloudflare configuration guide covers the wider setup. We configure Cloudflare’s request-limit rules on IP, path, method and header.

What belongs at the edge, and what does not

  • Block or challenge obvious floods, known bad user agents and paths that should never be public.
  • Cache anonymous responses so a spike of the same URL never reaches the origin. A cached page is cheaper than a rejected one.
  • Keep account-aware limits, plan quotas and “this API key has spent its budget” decisions in the application, where the identity actually exists.
  • Use a challenge such as Turnstile on signup and password reset when bots are the problem, and skip it on routes where a real API client cannot solve one.

We set both, then load-test that the origin stays up when the edge holds and degrades cleanly when a flood still gets through.

Traffic Management and Fair-Usage Policies

Traffic management is the product decision hiding inside the technical one. A free plan, a paying customer and an internal job should not share one bucket. Fair usage keeps one tenant from starving the others, and it gives you a way to sell higher limits without rewriting the API.

CallerTypical keySustained budgetBurstWhen the budget is spent
Anonymous visitorClient IP plus pathLowSmall429 or a cached public response
Logged-in customerUser idComfortable for a personShort spike allowed429 with Retry-After, UI explains the wait
API key, free planKey idDaily quota plus a per-minute capLimited429 and a usage header the client can read
API key, paid planKey id and planContracted quotaHigher429, then an alert to your team if it repeats
Internal workerService identitySeparate poolMatched to batch sizeQueue back-pressure, never a customer-facing error

We document the policy next to the API: which routes are metered, which headers come back (Retry-After at minimum), and which status means “slow down” rather than “forbidden”. A client that retries every 429 immediately makes an incident worse. This is the gap described in the OWASP note on unrestricted resource consumption.

Server racks glowing with green, yellow and blue lights in a dark data center

Security Measures Built Around Rate Limiting

A counter alone does not make an endpoint safe. It closes the gap where authentication, validation and caching are not enough: the caller may try, but not forever. We pair the budget with the controls that make it meaningful.

  • Authentication still decides access. A limit on an open admin route is not authorization.
  • Failures are tighter than successes. Ten wrong passwords are an attack; ten page views are a user. One shared counter either punishes customers or lets stuffing continue.
  • Expensive work gets its own quota. PDFs, image transforms, AI calls and unindexed search can cost as much as a thousand cheap requests.
  • Responses do not leak accounts. “User not found” and “wrong password” stay the same shape, and password reset is limited per address so it cannot map the user table or flood an inbox.
  • Webhooks are verified, then exempt. Signed callbacks from payment and shipping providers must not be dropped by the anonymous IP rule when the provider retries.
  • Lockouts expire. A short delay is safer than a permanent lock an attacker can trigger on someone else’s account.

Where Limits Live: Edge, Gateway, App and Data

Edge rules are fast and blind to your user table. Application counters know the tenant and the plan. We use the cheapest layer that still knows enough, and we treat the database as a safety net rather than the policy.

LayerKnows aboutGood atWeak atWe use it for
CDN / WAF (Cloudflare)IP, path, headers, bot scoreFloods, anonymous abuse, cheap rejectsPer-user plans and account stateFirst line in front of every public origin
API gateway or reverse proxyRoute, API key, client certificatePartner APIs, a shared policy across servicesDeep business rulesPublic and partner APIs with many backends
Application + RedisUser, tenant, plan, success or failureFair usage, login, quotas that must match billingStopping a flood already inside the processAnything that depends on who the caller is
Database and pool limitsConnections and query costLast-resort protection of the data storeA clear response to the clientA safety net, not the primary policy

A limit stored in one Node.js or PHP process is a different limit on every server, and it resets whenever that process restarts. Redis, with a short TTL and an atomic increment, gives every instance the same answer. If the edge already enforces a rule, we do not copy it into the app.

Choosing Windows, Bursts and Quotas

Fixed windows, sliding windows and token buckets disagree at a window boundary and on short bursts. A careless “100 per minute” rule can allow 200 in two seconds, or reject a normal checkout retry. We pick the algorithm per route. The trade-offs and sample code are in the guide linked above. The numbers themselves come from evidence:

  • Logs and metrics for the busiest hour: p95 and the worst legitimate burst, not the average.
  • A separate, stricter number for authentication failures.
  • A burst allowance so a page that fires several calls at once still loads.
  • A daily or monthly quota only where the commercial plan needs one; a per-second cap still sits underneath it.
  • A staging pass with a script that behaves well and a script that does not, so we see both the 429 and the unaffected customer path.

The numbers live in configuration, not as magic values in controllers, and every rejection logs which rule fired. Tuning after launch is expected; tuning without that log is guesswork.

Long-exposure light trails of cars passing under a dark urban bridge

Quotas for Multi-Tenant Products and Public APIs

Once you sell access, the quota becomes part of the offer. Free, team and enterprise plans need different budgets, and one shared key for a whole company is a different problem from one key per integration. We model the key, the tenant and the plan separately so an upgrade changes a quota rather than a deploy.

  • Keys rotate and revoke without disabling the tenant.
  • Response headers show the remaining budget so a partner can slow down before the hard stop.
  • Batch jobs and outbound webhooks spend a separate budget, so a nightly sync cannot use up the interactive quota.
  • Retries stay safe. A second attempt after a 429 must not create a second order or a second charge, which means idempotency keys sit in the same design as the quota.

Common Throttling Mistakes We Fix

Most of the setups we are asked to repair were added in a hurry after an incident. The same gaps show up:

  • One global limit for the whole site, so a scraper on search also blocks checkout.
  • IP-only rules behind a proxy, which either throttle the proxy or trust a spoofable header.
  • In-memory counters on a multi-instance deploy, so the effective limit is “limit times number of servers”.
  • A 429 with no Retry-After, which trains clients and bots to retry immediately.
  • No dashboard. You find out real users were blocked when they write to support.
  • Payment and shipping webhooks caught by the anonymous rule and silently dropped.
  • Permanent locks that an attacker can spring on a victim’s account.

What Drives the Cost

We estimate after a short look at the routes, the traffic and where the abuse or the slowdown actually is. The work grows with a few concrete factors:

  • How many routes need their own policy, especially login, search, checkout and public APIs.
  • Whether the limit is a single Nginx or Cloudflare rule, or a Redis-backed quota tied to billing plans.
  • How many app instances and environments must share the same counters.
  • Whether clients need documented headers, error shapes and a migration period for existing keys.
  • Load testing and dashboards, which we treat as part of the job rather than an extra.

One sensitive route on an existing Cloudflare and Redis stack is a small job. A public API with several plans and a transition period for current clients is a larger one. We say which it is before building.

How We Work

  1. Discovery: we list expensive, sensitive or already abused routes, and read logs, CDN rules and how clients identify themselves.
  2. Plan: we choose the layer, the key, the window and the response, and agree what must never be limited, such as health checks and signed webhooks.
  3. Build: we add edge rules, shared counters and application checks, and return a consistent 429 with Retry-After.
  4. Test: a polite client and an abusive one run against staging, on more than one app instance, while real user flows still pass.
  5. Launch: we start in report-only or with generous ceilings, then tighten once the graphs match what we expected.
  6. Support: dashboards, an alert on unusual 429 rates, and a note on changing a limit without hunting through code.

Why CodeWiz

  • Application and infrastructure together: we build the Laravel, Node.js, WordPress and API code, so the limit sits where the request is actually expensive.
  • Open-source first: Nginx, Redis and your existing framework carry the policy, with Cloudflare where the edge is the right place. You are not tied to a niche gateway licence.
  • Tailored to the route: login, checkout, search and partner APIs get different budgets. A single global number is the pattern we usually remove.
  • Fair pricing: premium development without premium prices, from Banja Luka, working remotely with clients locally and internationally.
  • Security and performance together: throttling, caching, Cloudflare and hardening stay in one brief. More about the studio is on the about CodeWiz page.

Frequently Asked Questions

How much does a throttling project cost?

A few routes on a stack that already has Cloudflare or Redis is a short engagement. A multi-tenant API with plans, usage headers and partner notes takes longer, because the policy is part of the product. We quote after looking at the routes and the traffic.

How long does a typical implementation take?

Login and a few expensive routes are often protected within days, including a staging test. A documented quota on an existing public API takes longer, mainly so current clients can adapt to the new headers and status codes.

Will real customers get blocked?

Only if the ceiling sits under a normal session. We size limits from your busy-hour traffic, allow a short burst for pages that fire several requests, and watch the 429 rate after launch so a person checking out is not the one who waits.

Is Cloudflare enough on its own?

It is the right place to stop anonymous floods and to challenge bots. It does not know that an API key is on the free plan, or that a password was wrong five times. Those rules live in the application. Most setups we ship use both.

Can you add limits to an existing Laravel, WordPress or Node.js app?

Yes. We usually leave the application in place and add edge rules plus a shared counter around the routes that need them. The Express middleware approach is the article linked above. WordPress and Laravel get the same policy with the tools those stacks already use.

Need Throttling That Fits the Product?

Tell us which routes are slow, expensive or already being abused, and we will propose a throttling setup that protects them without getting in the way of real users. Contact us to talk through the traffic, or see the full scope of our rate limiting and throttling services.