cd /news/developer-tools/api-rate-limiting-a-complete-guide-f… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-92924] src=dev.to β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

API Rate Limiting: A Complete Guide for Developers

API rate limiting is a critical technique for controlling client requests to protect backend infrastructure from overload, abuse, and unexpected costs. This guide explains the fundamentals, including common algorithms, HTTP 429 responses, and implementation strategies, and highlights how an edge API gateway can simplify rate limiting for developers.

read17 min views1 publishedAug 12, 2026

APIs are the foundation of modern applications. Whether you're building a SaaS platform, mobile application, AI product, or public developer API, your backend can receive thousands or even millions of requests every day.

But what happens when one user sends too many requests?

Without proper controls, excessive API traffic can cause:

API rate limiting is one of the most effective ways to control API traffic and protect backend infrastructure.

In this guide, we'll explain what API rate limiting is, how it works, common rate limiting algorithms, HTTP 429 responses, different rate limiting strategies, implementation approaches, best practices, and how an edge API gateway can simplify rate limiting.

API rate limiting is a technique used to control how many requests a client can make to an API within a specific period.

For example, an API might allow:

100 requests per minute per API key

If a client exceeds the limit, the API can temporarily reject additional requests.

A simple flow looks like this:

Client
   β”‚
   β”‚ Request
   β–Ό
API Gateway
   β”‚
   β”œβ”€β”€ Check rate limit
   β”‚
   β”œβ”€β”€ Within limit? ─── Yes ──► Backend API
   β”‚
   └── Limit exceeded? ── No ──► HTTP 429

The purpose isn't necessarily to prevent users from making requests.

Instead, rate limiting ensures that API resources are used within defined boundaries.

Imagine you have an API endpoint:

POST /api/login

A normal user might make a few requests.

But an attacker could send thousands of requests per second:

Request 1
Request 2
Request 3
...
Request 100,000

If every request reaches your application, your backend has to process all of them.

That can result in:

High traffic
     ↓
More application processing
     ↓
More database queries
     ↓
Higher CPU / memory usage
     ↓
Slower API responses
     ↓
Possible outage

With rate limiting:

100,000 requests
       ↓
Rate Limiter
       ↓
Allowed requests β†’ Backend
Blocked requests  β†’ HTTP 429

The backend receives only the traffic it is designed to handle.

API rate limiting is useful for several different problems.

Public APIs can be abused by automated scripts, bots, crawlers, or malicious users.

Rate limits make excessive usage more difficult.

Every API request consumes resources.

Depending on your application, a request may require:

Rate limiting helps prevent a sudden increase in traffic from overwhelming these resources.

Authentication endpoints are particularly important.

For example:

POST /api/login

Without rate limiting, an attacker could repeatedly attempt passwords.

You could apply a stricter policy:

Login:
5 requests / minute / IP

while allowing a less sensitive endpoint:

Products:
300 requests / minute / IP

More API requests can mean higher infrastructure costs.

This is especially important when your API calls expensive services such as:

Rate limiting can help prevent unexpected traffic from generating unexpected bills.

Suppose you have 1,000 customers.

Without rate limits, one customer could potentially consume most of your API capacity.

With customer-level limits:

Customer A β†’ 10,000 requests/hour
Customer B β†’ 10,000 requests/hour
Customer C β†’ 10,000 requests/hour

resources can be distributed more predictably.

At its simplest, a rate limiter keeps track of requests associated with a client.

For example:

API Key: abc123

Requests:
10:00:01 β†’ 1
10:00:05 β†’ 2
10:00:12 β†’ 3
10:00:20 β†’ 4
...

The rate limiter compares the request count against a configured limit.

For example:

Limit: 100 requests / minute

Current usage: 73

73 < 100
      ↓
Request allowed

When the limit is exceeded:

Limit: 100 requests / minute

Current usage: 101

101 > 100
       ↓
Request rejected
       ↓
HTTP 429 Too Many Requests

When a client exceeds an API rate limit, the standard HTTP status code is:

429 Too Many Requests

For example:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30

The response could contain:

{
  "error": "rate_limit_exceeded",
  "message": "Too many requests",
  "retryAfter": 30
}

The Retry-After

header can tell the client how long it should wait before trying again.

This allows well-designed clients to automatically back off instead of continuously retrying.

There isn't one universal rate limiting algorithm.

Several approaches are commonly used.

The most important ones are:

Let's look at each one.

The fixed window algorithm divides time into fixed intervals.

For example:

Limit:
100 requests / minute

The system creates windows:

10:00:00 ───────── 10:01:00
10:01:00 ───────── 10:02:00
10:02:00 ───────── 10:03:00

Each window gets its own request counter.

For example:

10:00 window
Requests: 73

73 < 100
Allowed

Once the counter reaches 100:

Requests: 101

101 > 100
Blocked

When the next minute starts, the counter resets.

The biggest problem is the boundary burst.

Imagine:

10:00:59 β†’ 100 requests
10:01:00 β†’ 100 requests

A client could potentially send 200 requests in approximately one second while technically staying within both windows.

This is called the fixed-window boundary problem.

A sliding window doesn't reset at fixed boundaries.

Instead, it continuously looks backward over a specific period.

For example:

Limit:
100 requests in the last 60 seconds

At 10:01:30, the system checks requests between:

10:00:30 β†’ 10:01:30

At 10:01:31, it checks:

10:00:31 β†’ 10:01:31

The window continuously moves forward.

A sliding window counter provides a compromise between fixed windows and fully timestamp-based sliding windows.

Instead of storing every request timestamp, the system uses counters from multiple windows and calculates an approximate current usage.

This reduces memory usage while providing smoother rate limiting than a simple fixed window.

It can be useful for high-volume APIs where exact timestamp tracking isn't necessary.

The token bucket algorithm is one of the most popular approaches for API rate limiting.

Imagine a bucket that holds tokens.

Each API request consumes one token.

For example:

Bucket capacity: 100 tokens
Refill rate:     10 tokens/second

Initially:

[● ● ● ● ● ● ● ● ● ● ...]
100 tokens

A request consumes a token:

Request
   ↓
Consume 1 token
   ↓
99 tokens remaining

Tokens are continuously added back at the configured refill rate.

This means clients can often handle short bursts while still respecting a long-term average rate.

Suppose:

Bucket capacity = 100
Refill rate = 10 tokens/second

A client can make a short burst of requests as long as tokens are available.

Once the bucket is empty:

No tokens
   ↓
Request rejected
   ↓
HTTP 429

The leaky bucket algorithm processes requests at a controlled rate.

Imagine requests entering a bucket:

Requests
 ↓ ↓ ↓ ↓ ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Bucket    β”‚
β”‚             β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
       β”‚
       β–Ό
   Controlled
     output

Requests are processed at a relatively consistent rate.

If the bucket becomes full, additional requests are rejected or dropped.

This makes the algorithm useful when you want to smooth traffic rather than allow large bursts.

The two algorithms are related but behave differently.

Feature Token Bucket Leaky Bucket
Allows bursts Yes Limited
Smooths traffic Moderate Strong
Common API use Very common Common
Flexible High Moderate
Request processing Based on tokens Based on output rate

A token bucket is often a good choice when an API needs to support legitimate short bursts.

A leaky bucket is useful when maintaining a more predictable request-processing rate is important.

Choosing the algorithm is only part of the problem.

You also need to decide what should be rate limited.

The simplest strategy is limiting requests by IP address.

For example:

100 requests/minute/IP

This is useful for public APIs and unauthenticated endpoints.

However, IP-based limits aren't perfect.

Many users can share the same public IP through:

Therefore, an IP address shouldn't always be treated as an individual user.

For developer APIs, API-key-based rate limiting is often more accurate.

For example:

API Key A β†’ 1,000 requests/hour
API Key B β†’ 10,000 requests/hour
API Key C β†’ 100,000 requests/hour

This also makes it easier to create different limits for different subscription plans.

For example:

Free
1,000 requests/month

Pro
100,000 requests/month

Enterprise
10,000,000 requests/month

Authenticated applications can rate limit based on user identity.

For example:

User ID: 12345
Limit: 500 requests/hour

This can provide better fairness than IP-based rate limiting.

Not every API endpoint has the same cost.

For example:

GET /products
500 requests/minute

POST /orders
100 requests/minute

POST /login
10 requests/minute

POST /generate-ai
20 requests/minute

Endpoint-specific limits are often more effective than one global limit.

SaaS applications frequently implement tier-based rate limits.

For example:

Plan Requests/minute Monthly Requests
Free 20 10,000
Pro 200 1,000,000
Business 1,000 10,000,000
Enterprise Custom Custom

This makes rate limiting part of the product's usage model.

A robust API often needs multiple layers of rate limiting.

For example:

Global limit:
100,000 requests/minute

        +

Per API key:
1,000 requests/minute

        +

Per IP:
100 requests/minute

        +

Endpoint:
POST /login β†’ 10 requests/minute

This creates multiple protection layers.

If one user starts abusing the API, they can be blocked without necessarily affecting everyone else.

There are several places where you can implement API rate limiting.

For example:

Client
  ↓
Node.js / NestJS
  ↓
Rate limiter
  ↓
Database

The request has already reached your infrastructure.

If thousands of malicious requests arrive, your application still has to process them before rejecting them.

You can implement rate limiting at the load-balancer layer.

Client
  ↓
Load Balancer
  ↓
Rate Limit
  ↓
Application

This moves traffic control earlier in the request path.

An API gateway is often a natural location for rate limiting.

Client
  ↓
API Gateway
  β”œβ”€β”€ Authentication
  β”œβ”€β”€ WAF
  β”œβ”€β”€ Rate Limiting
  β”œβ”€β”€ Caching
  └── Routing
       ↓
Backend

The advantage is that multiple backend services can share the same rate limiting policies.

An edge API gateway can enforce rate limits before requests travel to your origin.

User
  ↓
Nearest Edge
  ↓
Rate Limiter
  ↓
Allowed?
  β”‚
  β”œβ”€β”€ No β†’ HTTP 429
  β”‚
  └── Yes
       ↓
    Origin API

This can significantly reduce unnecessary origin traffic.

For APIs with large public traffic volumes, enforcing limits at the edge can be particularly useful.

Rate limiting becomes more complicated when your API runs on multiple servers.

Imagine:

                 API Gateway
                     β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό          β–Ό          β–Ό
       Server A   Server B   Server C

If each server keeps its own counter, you could accidentally allow more requests than intended.

For example:

Limit = 100 requests/minute

Server A β†’ 100
Server B β†’ 100
Server C β†’ 100

Total β†’ 300 requests

The intended limit was 100, but 300 requests were allowed.

This is why distributed rate limiting often requires a shared state system.

Common technologies include:

Redis is frequently used for distributed rate limiting because it provides fast in-memory operations.

A simplified architecture:

              API Gateway
                   β”‚
                   β–Ό
               Rate Limiter
                   β”‚
                   β–Ό
                 Redis
                   β”‚
                   β–Ό
                Counter
                   β”‚
             β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
             β”‚            β”‚
          Allowed       Blocked
             β”‚            β”‚
             β–Ό            β–Ό
          Backend       HTTP 429

A key might look like:

rate_limit:user:12345

or:

rate_limit:ip:203.0.113.10

The counter can expire automatically after the configured time window.

A well-designed API should communicate rate limit information to clients.

Common headers include:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 27
X-RateLimit-Reset: 1723456789

When the limit is exceeded:

HTTP/1.1 429 Too Many Requests
Retry-After: 30

Header naming conventions can vary between APIs, so consistency and clear documentation are more important than a particular custom header name.

A client shouldn't continuously retry immediately after receiving HTTP 429.

Bad behavior:

429
 ↓
Retry
 ↓
429
 ↓
Retry
 ↓
429
 ↓
Retry

This can make the situation worse.

Instead, clients should use backoff.

For example:

Request
  ↓
429
  ↓
Wait
  ↓
Retry
  ↓
429
  ↓
Wait longer
  ↓
Retry

A common strategy is exponential backoff with jitter.

For example:

1 second
2 seconds
4 seconds
8 seconds
16 seconds

Random jitter can be added so that many clients don't retry simultaneously.

Different endpoints have different costs.

A database-heavy endpoint should usually have a different limit from a lightweight endpoint.

Use the standard:

429 Too Many Requests

when the client exceeds the configured request rate.

Use Retry-After

where appropriate.

This makes your API easier to consume.

Developers should know:

Poorly documented rate limits can lead to frustrating API integrations.

Depending on your API, consider combining:

IP
API Key
User
Endpoint
Organization
Subscription Plan

For example:

GET /health
β†’ 1,000 req/min

GET /products
β†’ 500 req/min

POST /generate
β†’ 20 req/min

The limits should reflect the actual resource cost.

IP addresses can represent many users.

For authenticated APIs, API keys, user IDs, or organization IDs often provide more meaningful rate limiting identities.

Track:

This can help distinguish legitimate growth from abuse.

Rate limiting isn't a complete security solution.

For public APIs, consider combining:

DDoS protection
      +
WAF
      +
Authentication
      +
Rate limiting
      +
Bot detection
      +
Monitoring

The terms rate limiting and throttling are sometimes used interchangeably, but they can describe slightly different behaviors.

Sets a maximum number of requests that can be accepted during a period.

100 requests/minute

Can refer more broadly to controlling or slowing traffic when a threshold is reached.

For example:

Normal traffic
      ↓
High traffic
      ↓
Slow processing
      ↓
Extreme traffic
      ↓
Reject requests

The exact terminology depends on the API platform.

Rate limits and quotas solve different problems.

Controls how quickly requests can be made.

100 requests/minute

Controls how many requests can be consumed over a longer period.

1,000,000 requests/month

You can use both:

Per minute:
1,000 requests

Per month:
10 million requests

This is common in SaaS and developer API pricing.

Rate limiting is particularly important for AI applications.

An AI request may consume significantly more resources than a normal API request.

For example:

GET /products
β†’ inexpensive

POST /generate
β†’ model inference
β†’ expensive

An AI platform might therefore use several limits:

Requests/minute
Tokens/minute
Tokens/day
Requests/day
Monthly usage

For example:

Free:
10 requests/minute
100,000 tokens/month

Pro:
100 requests/minute
5,000,000 tokens/month

AI APIs often need both request-based limits and usage-based quotas.

Webhooks can also benefit from rate limiting.

Imagine a third-party service sends:

10,000 webhook events

within a few seconds.

Your webhook endpoint may become overloaded.

A gateway can help control the traffic before it reaches your application:

Webhook Provider
       β”‚
       β–Ό
API Gateway
       β”‚
       β”œβ”€β”€ Rate Limit
       β”œβ”€β”€ WAF
       β”œβ”€β”€ Validation
       └── Queue / Routing
       β”‚
       β–Ό
Webhook Service

This is particularly useful for SaaS platforms that receive high-volume events.

Managing rate limiting independently in every backend service can become difficult as your infrastructure grows.

EdgeWrap provides an edge API gateway layer that can sit in front of your existing APIs.

Instead of implementing traffic controls independently across multiple services:

Client
  β”‚
  β”œβ”€β”€β”€β”€β–Ί User API
  β”‚
  β”œβ”€β”€β”€β”€β–Ί Order API
  β”‚
  └────► Payment API

you can put a gateway in front:

                    Client
                      β”‚
                      β–Ό
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  EdgeWrap β”‚
                β”‚           β”‚
                β”‚    WAF    β”‚
                β”‚ Rate Limitβ”‚
                β”‚   Cache   β”‚
                β”‚  Routing  β”‚
                β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
                      β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β–Ό           β–Ό           β–Ό
       User API    Order API   Payment API

This allows rate limiting and other API policies to be managed at a centralized layer.

You can configure your gateway through the EdgeWrap dashboard and use the EdgeWrap documentation for configuration and implementation details.

A production API might use multiple controls:

                         Internet
                            β”‚
                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    EdgeWrap   β”‚
                    β”‚               β”‚
                    β”‚ DDoS          β”‚
                    β”‚ WAF           β”‚
                    β”‚ Bot Detection β”‚
                    β”‚               β”‚
                    β”‚ Rate Limiting β”‚
                    β”‚               β”‚
                    β”‚ Cache         β”‚
                    β”‚               β”‚
                    β”‚ Analytics     β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚ API Gateway β”‚
                     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β–Ό             β–Ό             β–Ό
          Service A      Service B      Service C
              β”‚             β”‚             β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β–Ό
                         Database

The important architectural principle is to reject unnecessary traffic as early as possible.

If a request can be safely rejected at the edge, there's little reason to send it through your application servers and database.

There is no universal value such as:

100 requests/minute

that works for every API.

Instead, consider:

How expensive is the request?

How many requests can your infrastructure safely process?

How frequently do legitimate users make requests?

Do users naturally send bursts?

Should different customers have different limits?

Could the endpoint be targeted by attackers?

For example:

                    Suggested Policy

Health Check       β†’ High limit
Product Listing    β†’ Medium/High
Search             β†’ Medium
Login              β†’ Low
Password Reset     β†’ Very Low
AI Generation      β†’ Low + Token Quota
Payment            β†’ Low + Authentication

The best rate limit is based on your application's actual behavior and capacity.

If legitimate clients frequently receive HTTP 429 responses, your API becomes difficult to use.

A limit that doesn't meaningfully protect your infrastructure isn't useful.

This still consumes backend resources.

For high-risk public APIs, earlier enforcement can be more effective.

Shared networks can cause legitimate users to affect each other.

Developers need to know how to handle HTTP 429 responses.

Per-server counters can produce incorrect global limits when traffic is distributed across multiple servers.

You need visibility into why requests are being blocked.

Otherwise, it's difficult to distinguish abuse from legitimate traffic growth.

Before deploying an API, consider this checklist:

☐ Define limits per endpoint
☐ Choose a rate limiting algorithm
☐ Decide what identifies a client
☐ Configure burst behavior
☐ Return HTTP 429
☐ Consider Retry-After
☐ Document limits
☐ Monitor rate-limit events
☐ Protect authentication endpoints
☐ Protect expensive operations
☐ Consider distributed rate limiting
☐ Combine rate limiting with WAF/DDoS protection
☐ Review limits as traffic grows

API rate limiting controls how many requests a client can make to an API during a specific period. It helps prevent abuse, protect backend infrastructure, control costs, and ensure fair resource usage.

The API typically returns the HTTP 429 Too Many Requests

status code. The response may also include a Retry-After

header indicating when the client should try again.

There is no single best algorithm. Fixed windows are simple, sliding windows provide smoother control, and token buckets are useful when you need to support controlled bursts.

It depends on your application. IP-based limits work well for unauthenticated traffic, while API-key or user-based limits are often more appropriate for authenticated developer APIs.

Rate limiting can help reduce abusive traffic, but it should not be considered a complete DDoS protection solution. Large-scale DDoS attacks generally require dedicated edge-level mitigation.

Yes. By preventing excessive requests from reaching your backend or expensive third-party services, rate limiting can help control infrastructure and API usage costs.

Rate limiting controls the speed of requests, such as 100 requests per minute. A quota controls total usage over a longer period, such as 1 million requests per month.

Rate limiting can be implemented inside your application, at a load balancer, API gateway, or edge layer. For protecting origin infrastructure, enforcing limits closer to the edge can prevent unnecessary requests from reaching your backend.

API rate limiting is a fundamental part of building reliable and secure APIs.

A good rate limiting strategy helps you:

The most effective implementations usually combine several controls:

                 API Protection
                       β”‚
       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
       β–Ό               β–Ό                β–Ό
  Authentication   Rate Limiting       WAF
       β”‚               β”‚                β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β–Ό
                 DDoS Protection
                       β”‚
                       β–Ό
                    Caching
                       β”‚
                       β–Ό
                    Backend

As your API grows, implementing rate limiting directly inside every service can become difficult to maintain. A centralized API gateway can move these concerns into a dedicated infrastructure layer.

If you want to manage API traffic at the edge, EdgeWrap provides a managed API gateway with rate limiting alongside security, caching, routing, reliability, and API observability features. You can learn more about configuring it in the EdgeWrap documentation.

── more in #developer-tools 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/api-rate-limiting-a-…] indexed:0 read:17min 2026-08-12 Β· β€”