Prompt
How do I test API rate limits and retry behavior?
Latest observation
To test API rate limits and retry behavior, you want to verify two things:
- What happens when you send too many requests
- Whether your client retries correctly after being throttled or temporarily failing
Here’s a practical way to test both.
1) Understand the rate limit policy first
Check the API docs for:
- Limit type: per second, per minute, per hour, per user, per token, etc.
- What error code is returned: often
429 Too Many Requests - Headers provided:
Retry-AfterX-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
This tells you what to expect and how to assert behavior.
2) Test rate limiting by intentionally exceeding the limit
Send requests faster than the allowed threshold.
Example approach
- If the limit is 10 requests/minute, send 15–20 requests in quick succession.
- Observe:
- When the API starts rejecting requests
- Whether it returns
429 - Whether headers indicate when to retry
Simple cURL loop
for i in {1..20}; do
curl -i https://api.example.com/resource
done
Better: concurrent load
Use a load tool like:
k6JMeterLocustheyab(ApacheBench)
This is better if the API uses short-window limits or concurrent request limits.
3) Verify retry behavior for retryable errors
Your client should usually retry only on transient failures, such as:
429 Too Many Requests500 Internal Server Error502 Bad Gateway503 Service Unavailable504 Gateway Timeout
It should usually not retry on:
400 Bad Request401 Unauthorized403 Forbidden404 Not Found
4) Test backoff logic
A good retry strategy usually includes:
- Exponential backoff
- Jitter to avoid retry storms
- Respecting Retry-After if present
- A max retry count
Example expected behavior
If your client gets a 429:
- Wait for
Retry-Afterseconds if provided - Otherwise wait using backoff:
- 1s
- 2s
- 4s
- 8s
- Stop after max retries
5) Validate your client doesn’t retry too aggressively
Check that:
- It does not retry indefinitely
- It stops after the configured maximum
- It doesn’t retry non-retryable errors
- It uses increasing delays, not constant rapid retries
6) Simulate failures if you can’t hit the real limit
If the real API is hard to throttle safely, mock or stub responses.
Useful tools
- WireMock
- MockServer
- Postman mock server
- A local test proxy that returns
429/503
This lets you confirm retry logic without stressing production.
7) Check idempotency
If requests may be retried, ensure they’re safe to repeat.
- Safe to retry:
GETPUTif idempotentDELETEif idempotent
- Risky to retry:
POSTunless the API supports idempotency keys
For write operations, use:
- Idempotency-Key headers
- Server-side deduplication
This prevents duplicate charges, orders, or records.
8) Assertions to include in tests
Your tests should verify:
429is returned when the limit is exceededRetry-Afteris honored- Retry count matches configuration
- Backoff intervals increase correctly
- Requests succeed after the limit resets
- Non-retryable errors are not retried
- Idempotent behavior prevents duplicates
9) Example test cases
Rate limit test
- Send requests below the limit → all succeed
- Send requests above the limit → some fail with
429 - Wait for reset window
- Send again → succeed
Retry test
- Mock
429withRetry-After: 2 - Confirm client waits ~2 seconds
- Confirm it retries once
- Confirm it stops after max retries if failures continue
10) Example pseudo-logic for client retries
if response.status in [429, 500, 502, 503, 504]:
retry up to N times
if Retry-After header exists:
sleep(Retry-After)
else:
sleep(exponential_backoff_with_jitter)
else:
do not retry
11) Best practices
- Test in a sandbox/staging environment
- Avoid rate-limit tests against production unless explicitly safe
- Use small bursts and monitor logs/metrics
- Validate both client and server side behavior
- Add alerts for sustained
429rates
If you want, I can also give you:
- a Postman test plan
- a Python script to test rate limits
- a pytest/unit-test example for retry logic
- a k6 load test script