Rate Limiting & Throttling

Introduction

APIs are designed to receive requests from users, browsers, mobile applications, partner systems, automation jobs, microservices, and third-party clients. In a healthy system, those requests arrive at a volume the API can handle. In the real world, however, traffic is not always healthy. Attackers may send abusive traffic, bots may scrape data, users may retry too aggressively, integrations may have defects, and legitimate traffic may spike suddenly during business events. If an API accepts unlimited requests, the server can become overloaded and unreliable.

Rate Limiting and Throttling are two important mechanisms used to control excessive API usage. They protect servers from overload, reduce denial-of-service risk, slow down brute-force attempts, limit credential stuffing, discourage automated scraping, ensure fair usage among clients, and improve API stability. These controls are part of both API security and API performance design because they protect availability and resource consumption.

For API testers, rate limiting and throttling are practical topics. A functional API test may prove that one request returns `200 OK`, but that does not prove the API behaves correctly when the same client sends one hundred, one thousand, or ten thousand requests. A secure and reliable API must define how many requests are allowed, how excess requests are handled, what response is returned, which headers are provided, when the limit resets, and whether different users or API keys are tracked independently.

Rate limiting is especially important because APIs are easy to automate. A browser user may click a button once, but a script can send thousands of requests quickly. Without controls, an attacker can abuse login endpoints, OTP endpoints, search APIs, product APIs, export APIs, payment APIs, and expensive reporting endpoints. Rate limiting and throttling help the API remain available and predictable even when traffic is aggressive or poorly behaved.

What Is Rate Limiting?

Rate Limiting is a mechanism that restricts the number of API requests a client can make within a specified time period. The limit may be defined per second, per minute, per hour, per day, or any other time window. For example, an API may allow one hundred requests per minute per user. If the client sends more than one hundred requests during that minute, the API rejects the excess requests.

A simple definition is this: Rate Limiting limits how many requests a client can send within a defined time window. The purpose is to prevent excessive usage from consuming too much backend capacity or abusing business functionality.

API Policy
100 requests
per minute

101st request
  |
HTTP/1.1 429 Too Many Requests

Rate limiting is usually enforced by an API gateway, load balancer, reverse proxy, service mesh, application middleware, or dedicated rate-limit service. In some systems, multiple layers enforce different limits. A gateway may enforce global limits, while the application enforces user-specific business limits.

What Is Throttling?

Throttling controls how the API handles requests when traffic exceeds predefined limits or when the system needs to manage load dynamically. Depending on the implementation, throttling may delay requests, slow down responses, queue requests, temporarily reject requests, or gradually reduce request throughput. It is not only about counting requests; it is about shaping traffic so the service remains stable.

A simple definition is this: Throttling controls or slows excessive API requests instead of allowing unlimited access. Some APIs use the terms rate limiting and throttling interchangeably, but they can represent slightly different behaviors. Rate limiting commonly rejects requests beyond a threshold. Throttling may delay, queue, or slow requests to smooth traffic.

Client
  |
Too Many Requests
  |
API
  |
Slow Down, Delay, Queue, or Reject
  |
Continue After Limit Resets

Throttling can be useful when short bursts are acceptable but sustained overload is not. For example, an API may allow a brief burst of traffic and then slow requests down once the burst capacity is consumed. This helps absorb normal traffic variation without immediately rejecting every extra request.

Why Rate Limiting and Throttling Are Needed

Without request controls, any client can consume excessive server resources. A poorly written mobile app may retry continuously when a network error occurs. A bot may scrape product prices every second. An attacker may try thousands of passwords against a login API. A reporting client may request huge exports repeatedly. A partner integration may accidentally run an infinite loop. Even legitimate clients can overload a system when they behave unexpectedly.

Without Protection:
Client
  |
Unlimited Requests
  |
Server Overloaded
  |
Application Crash

With rate limiting, the API defines a controlled boundary. Requests within the limit are processed. Requests beyond the limit are rejected or delayed. This protects CPU, memory, database capacity, network bandwidth, external service calls, queue depth, and other resources. It also protects users by keeping the service available for everyone rather than allowing one client to consume disproportionate capacity.

With Rate Limiting:
Client
  |
Request Limit
  |
Server Protected

These controls are also security controls. Rate limiting can reduce brute-force attacks, credential stuffing, OTP abuse, account enumeration, inventory scraping, price scraping, automated sign-ups, denial-of-service attempts, and excessive resource consumption. It does not replace authentication, authorization, or input validation, but it adds an important availability and abuse-prevention layer.

Rate Limiting Workflow

A typical rate limiting workflow starts when the client sends a request to the API gateway or backend. The rate-limiting layer identifies the client using one or more keys, such as user account, API key, IP address, OAuth client, access token, organization, or subscription plan. It then checks a counter or bucket for the current time window. If the request is within the allowed limit, it proceeds. If the limit is exceeded, the API returns a denial response such as `429 Too Many Requests`.

Client
  |
API Gateway
  |
Request Counter
  |
Within Limit?
  |
Yes -> Process Request
No  -> 429 Too Many Requests

This flow sounds simple, but implementation details matter. The limit must be tracked consistently across distributed servers. The reset time must be clear. The response should tell clients how to behave. High-risk endpoints may need stricter limits than normal read endpoints. Authenticated and unauthenticated callers may have different limits. Paid subscription tiers may have different quotas.

Difference Between Rate Limiting and Throttling

AreaRate LimitingThrottling
Main purposeRestricts number of requestsControls request rate after limits or load conditions
Typical behaviorRejects requests beyond the limitMay delay, queue, slow, or reject requests
Primary goalPrevent excessive API usageManage server load smoothly
Common response429 Too Many RequestsDelayed response or 429 Too Many Requests

In practice, many teams use these terms together because both deal with controlling traffic. From a testing perspective, the important question is not the label. The important question is what the API contract promises. Does the API reject excess calls immediately? Does it delay responses? Does it queue background work? Does it include retry guidance? Does it recover correctly when the limit resets?

Common Rate Limits

Rate limits vary by API, endpoint, client type, and business model. Some APIs limit requests per second to protect real-time systems. Others limit requests per minute for normal application usage. Public developer APIs often use hourly or daily quotas. Enterprise APIs may have organization-level monthly limits or subscription-plan limits.

Limit TypeExampleCommon Use
Per second10 requests per secondProtect high-frequency endpoints
Per minute100 requests per minuteControl normal API traffic
Per hour5,000 requests per hourManage public API usage
Per day100,000 requests per dayEnforce quotas and plans

Actual limits should be based on system capacity, endpoint cost, risk level, customer expectations, and business requirements. A login endpoint usually needs stricter protection than a public product browsing endpoint. A heavy report-generation endpoint may need lower limits than a simple reference-data endpoint.

What Rate Limits Are Based On

APIs can apply rate limits using different identifiers. A public endpoint may limit by IP address. An authenticated API may limit by user account or access token. A partner API may limit by API key or OAuth client. A SaaS product may limit by organization or tenant. A paid API may limit by subscription plan.

The choice matters. IP-based limits can be useful for unauthenticated traffic, but they may affect many users behind the same network. Token-based limits are more precise for authenticated APIs. API key limits are useful for partner applications, but they may not distinguish individual end users. Organization-level limits help protect multi-tenant capacity. Plan-based limits support commercial API quotas.

Testers should verify that limits are applied to the intended identity. If User A exceeds the limit, User B should not be blocked unless the limit is shared by design. If one API key reaches its quota, another API key should continue if the contract says keys are tracked independently. If a limit is per organization, users within the same organization may share quota. These details must be validated against the design.

HTTP 429 Too Many Requests

When a client exceeds the configured limit, APIs commonly return:

HTTP/1.1 429 Too Many Requests

This status code tells the client that the request was not processed because the client sent too many requests in a given amount of time. The response should be safe, predictable, and documented. It should not expose internal counters, infrastructure details, or sensitive implementation information beyond what clients need.

A `429` response is not always an application failure. It may be the correct behavior. Automated tests should expect `429` when they intentionally exceed limits. Monitoring should distinguish between a few expected rate-limit responses and a sudden spike that may indicate abuse or client defects.

Retry-After Header

Many APIs include a `Retry-After` header when a rate limit is exceeded. This header tells the client how long to wait before retrying. The value may be a number of seconds or an HTTP date depending on the API design.

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

This means the client should wait sixty seconds before sending more requests. Good clients use this information to avoid aggressive retry loops. Without retry guidance, clients may keep retrying immediately and make the overload worse.

Testers should verify whether the API includes `Retry-After` or equivalent rate-limit information when documented. They should also verify that the value is reasonable and that requests succeed again after the reset period when the limit has cleared.

Rate Limit Headers

Many APIs return headers that help clients understand their current quota. Common legacy-style headers include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and `X-RateLimit-Reset`. Some APIs use standardized `RateLimit-*` headers or provider-specific names.

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 25
X-RateLimit-Reset: 1712345678
HeaderPurpose
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests left in the current window
X-RateLimit-ResetTime when the limit resets
Retry-AfterHow long the client should wait before retrying

Headers should be tested for accuracy. The remaining count should decrease as requests are made. Reset timing should match the configured window. When the limit is exceeded, the API should return the expected headers if the contract requires them. Incorrect headers can cause client retry behavior to become inefficient or unstable.

Common Rate Limiting Algorithms

A fixed window algorithm counts requests during a fixed time interval, such as one minute. If the limit is one hundred requests per minute, the counter resets at the start of each new minute. Fixed windows are simple, but they can allow bursts near window boundaries. A client may send one hundred requests at the end of one minute and another one hundred at the start of the next minute.

A sliding window algorithm uses a continuously moving time range rather than a strict calendar boundary. This provides smoother request distribution because it evaluates recent traffic more accurately. Sliding windows are often more precise but may require more complex tracking.

A token bucket algorithm gives each client a bucket of tokens. Each request consumes a token. Tokens are replenished over time. If the bucket has tokens, requests are accepted. If tokens run out, requests are rejected or throttled. Token bucket supports controlled bursts because clients can temporarily use saved tokens.

A leaky bucket algorithm processes requests at a steady rate. Incoming requests enter a queue or bucket, and the system drains them at a constant pace. Excess requests may be queued or rejected if capacity is full. This approach is useful for smoothing bursts and protecting backend systems from sudden traffic spikes.

Why APIs Use Rate Limiting

APIs use rate limiting to prevent denial-of-service attacks, brute-force attacks, credential stuffing, bot abuse, excessive resource consumption, scraping, repeated OTP abuse, account enumeration, expensive queries, and server overload. Some of these risks are malicious, while others are accidental. A client bug can create traffic that looks just as harmful as an attack.

Login endpoints often need strict limits because attackers can try many passwords. OTP endpoints need limits because sending SMS or email codes can create cost and user annoyance. Search and listing APIs need limits because bots can scrape data. Export and reporting APIs need limits because they may trigger expensive backend processing. Payment and transaction APIs need limits because repeated requests can create financial or business risk.

Rate limiting also supports fairness. If one client consumes all available capacity, other users suffer. Limits ensure that API access is distributed according to policy, plan, role, or business priority.

Rate Limiting in API Testing

QA engineers should verify request limits, reset intervals, `429` responses, `Retry-After` headers, rate-limit headers, different user limits, different API key limits, burst traffic handling, and recovery after reset. Testing should match the documented contract and the risk of each endpoint.

A basic within-limit test sends requests up to the allowed threshold and expects normal success responses. An exceed-limit test sends one more request and expects `429 Too Many Requests` or the documented throttling behavior. A retry-after-reset test waits until the reset time and verifies that the API accepts requests again. A different-client test verifies that User A's limit does not incorrectly block User B when limits are supposed to be tracked independently.

Testers should be careful with rate-limit tests because they intentionally create repeated traffic. These tests should run in controlled environments with known limits. Automated suites should avoid creating unnecessary load, especially in shared environments. For production monitoring, synthetic tests should be conservative and approved.

Example Test Cases

A within-limit test sends one hundred requests when the policy allows one hundred requests per minute. The expected result is that all requests within the limit succeed, assuming the requests are otherwise valid. The status may be `200 OK`, `201 Created`, or another expected success code depending on the operation.

An exceed-limit test sends the one hundred first request when the limit is one hundred. The expected result is `429 Too Many Requests`. The response may include `Retry-After` and rate-limit headers. The body should be controlled and should not expose internal infrastructure details.

A retry-after-reset test waits until the reset time and sends another request. The expected result is normal processing again. A different API key test sends requests using User A or API Key A until the limit is reached, then sends a request using User B or API Key B. If the policy tracks clients independently, User B should not be blocked by User A's usage.

An invalid API key test is different from a rate-limit test. If the API key is invalid, the expected response is commonly `401 Unauthorized`, not `429`. This distinction helps testers separate authentication failures from rate-limit behavior.

REST Assured Example

REST Assured can automate rate-limit checks in Java. A simple test may send repeated requests and assert that the status changes after the configured threshold.

for (int i = 1; i <= 105; i++) {
    given()
        .header("Authorization", "Bearer " + token)
    .when()
        .get("/employees")
    .then()
        .statusCode(i <= 100 ? 200 : 429);
}

Real tests should account for timing, parallel tests, shared environments, and existing request counts. If other tests use the same token or API key, the remaining quota may already be lower. To reduce flakiness, use isolated credentials or configurable test limits in a controlled environment.

Postman Example

Postman can test rate limiting through the Collection Runner or Newman. Testers can send a sequence of requests quickly and verify status codes, rate-limit headers, `Retry-After`, response body, and response times. This is useful for exploratory validation and for demonstrating behavior to a team.

Postman tests can assert that a `429` response appears after the threshold, that remaining counts decrease, and that retry information is present. If a provider uses plan-specific quotas, testers can run the same collection with different API keys or environments. As always, avoid using real production credentials in shared collections.

Karate Example

Karate can validate a single permitted request and can also be used in repeated execution to observe the rate limit. A normal request may look like this:

Given header Authorization = 'Bearer ' + token
When method GET
Then status 200

When repeated enough times in a controlled test, the same endpoint should eventually produce `429 Too Many Requests` if the configured rate limit is exceeded. For stable automation, the suite should avoid relying on uncontrolled timing or shared counters. Clearly name the scenario so reports show that the `429` is expected behavior, not a random failure.

Real-World Examples

Public developer APIs commonly use rate limits to protect shared infrastructure. GitHub APIs, for example, apply different limits based on whether the caller is authenticated and which token or account is used. Large cloud APIs often apply quotas by project, user, region, or service. These limits help providers keep systems reliable for many clients.

Banking APIs use limits to reduce fraud, protect transaction endpoints, and prevent automated abuse. Login, OTP, fund transfer, beneficiary creation, and transaction history endpoints may have different thresholds because their risk and cost differ. E-commerce APIs use limits to reduce inventory scraping, price scraping, bot purchases, coupon abuse, and account takeover attempts.

Internal enterprise APIs also need rate limits. A faulty batch job can overload internal services as easily as an external attacker. Service-to-service limits, queue limits, and retry policies help protect backend stability.

Best Practices

Define appropriate rate limits based on endpoint risk, backend cost, traffic patterns, user expectations, and business requirements. Return `429 Too Many Requests` when limits are exceeded, unless the API uses a documented throttling behavior. Include `Retry-After` or equivalent rate-limit information so clients know when to retry safely.

Apply limits per user, API key, OAuth client, IP address, organization, access token, or subscription plan where appropriate. Do not use one identifier blindly for every situation. Protect login and OTP endpoints with stricter limits. Use throttling to smooth short bursts. Monitor excessive request patterns and log rate-limit violations safely.

Document limits clearly for API consumers. Clients should know the allowed request volume, reset behavior, response code, retry guidance, and whether limits differ by endpoint or plan. Good documentation reduces accidental abuse from legitimate clients.

Common Mistakes

The most serious mistake is having no rate limiting. Unlimited requests increase the risk of denial-of-service attacks, brute-force attempts, bot abuse, scraping, and resource exhaustion. Another mistake is setting limits so high that they do not protect anything. A limit must reflect actual capacity and risk.

No retry information is another common problem. If clients do not know when to retry, they may retry immediately and worsen the load. Applying the same limit everywhere can also be wrong. Login should usually be stricter than product search. Heavy exports should usually be stricter than lightweight reads.

Ignoring burst traffic can create either instability or poor user experience. Some APIs should tolerate small bursts while blocking sustained abuse. Others should be strict immediately. The design should match the business need and the backend capacity.

Common HTTP Status Codes

ScenarioCommon Status Code
Request accepted200 OK
Resource created201 Created
Too many requests429 Too Many Requests
Invalid authentication401 Unauthorized
Access denied403 Forbidden

Rate-limit failures should not be confused with authentication or authorization failures. Invalid credentials should fail as authentication. Insufficient permissions should fail as authorization. Excessive valid requests should trigger rate limiting or throttling behavior.

Practical Review Checklist

When reviewing rate limiting, start by asking which endpoints need protection. Login, password reset, OTP, search, listing, export, payment, report, file upload, and expensive query endpoints are common candidates. Then identify the limit basis: user, token, API key, IP address, organization, OAuth client, or plan.

Next, verify behavior within the limit, at the limit, beyond the limit, and after reset. Confirm the response status, response body, `Retry-After` header, remaining count, reset time, and independent tracking across clients. If burst traffic is supported, verify that short bursts are handled according to design and sustained excess traffic is controlled.

Finally, review operational visibility. Are rate-limit violations logged? Are unusual spikes monitored? Can support teams explain why a client was limited? Are limits documented for consumers? Rate limiting works best when implementation, testing, monitoring, and documentation align.

Avoiding Flaky Rate Limit Tests

Rate-limit tests can become flaky if they share credentials, run in parallel without coordination, or depend on exact wall-clock timing. If several automated tests use the same user, token, API key, or IP address, one test may consume quota before another test starts. The second test may then receive `429 Too Many Requests` earlier than expected. This does not always mean the API is wrong; it may mean the test setup is not isolated.

A stronger approach is to use dedicated test clients for rate-limit scenarios. If possible, configure lower limits in a controlled test environment so the test does not need to send hundreds or thousands of requests. For example, a test-only policy of five requests per minute is easier to validate than a production policy of ten thousand requests per hour. The behavior is the same, but the test is faster and less disruptive.

Tests should also allow small timing tolerances. Reset windows may depend on gateway clocks, distributed counters, cache propagation, or algorithm type. A fixed-window implementation behaves differently from a sliding-window or token-bucket implementation. Instead of assuming a reset happens at an exact millisecond, tests should follow documented headers such as `Retry-After` or `X-RateLimit-Reset` where available.

Finally, rate-limit tests should be separated from normal functional tests when they create repeated traffic. They may be placed in a security, resilience, or performance-focused suite that runs in a controlled schedule. This keeps regular regression tests fast while still validating that the API protects itself from excessive request volume.

Interview Questions

A common interview question is: what is Rate Limiting? A strong answer is that Rate Limiting restricts how many API requests a client can make within a specified time period, such as one hundred requests per minute. It protects the API from excessive usage and abuse.

Another question is: what is Throttling? Throttling controls how an API handles requests after limits are exceeded or when the system needs to manage load. It may delay, slow, queue, or reject requests depending on implementation.

Interviewers may ask which HTTP status code indicates the rate limit has been exceeded. The common answer is `429 Too Many Requests`. They may ask about the `Retry-After` header. It tells the client how long to wait before retrying. They may also ask what testers should verify: request limits, `429` responses, rate-limit headers, reset behavior, burst handling, different client limits, and recovery after reset.

Interview-Ready Explanation

Rate Limiting and Throttling are mechanisms used to protect APIs from excessive usage and abuse. Rate Limiting restricts the number of requests a client can make within a defined time period, such as one hundred requests per minute. When the limit is exceeded, the API commonly returns `429 Too Many Requests` and may include a `Retry-After` header that tells the client when to retry.

Throttling controls how requests are handled when limits are exceeded or traffic becomes too heavy. Depending on the implementation, it may delay requests, slow responses, queue work, or reject additional calls. These controls help prevent denial-of-service attacks, brute-force attempts, credential stuffing, bot abuse, scraping, and resource exhaustion while ensuring fair API usage and stable performance.

During API testing, testers should verify the configured limits, response status codes, retry headers, rate-limit headers, reset timing, independent tracking by user or API key, burst behavior, and recovery after the limit resets. Rate limiting should be tested in controlled environments because the tests intentionally generate repeated requests.

Key Takeaway

Rate limiting and throttling protect API availability. They prevent one client, script, attacker, or faulty integration from overwhelming the service or abusing sensitive workflows. These mechanisms are both security controls and performance controls because they reduce misuse and keep backend systems stable.

For testers, the practical rule is to validate traffic boundaries, not only single-request behavior. Confirm that normal traffic works, excessive traffic is controlled, clients receive useful retry guidance, limits reset correctly, and different users or API keys are tracked according to the design. A reliable API must behave safely under repeated requests as well as under normal requests.