RATE-002 recommended general
Graceful 429 handling
Rate-limited requests return proper 429 responses with helpful information
Question to ask
"What does your client actually do when it gets rate-limited?"
Verification guide
Severity: Recommended
When rate limits are hit, the response should be a proper 429 Too Many Requests with helpful information. The application shouldn't crash or return misleading errors.
Check automatically:
- Check for 429 status code handling:
# Explicit 429 responses in code
grep -rE "429|Too Many Requests|TooManyRequests" src/ lib/ app/ --include="*.ts" --include="*.js" --include="*.py" 2>/dev/null
# Rate limiter response configuration
grep -rE "statusCode.*429|status.*429|message.*rate|response.*limit" src/ lib/ app/ 2>/dev/null
- Check for Retry-After header (nice-to-have):
# Retry-After header configuration
grep -rE "Retry-After|retryAfter|retry-after" src/ lib/ app/ 2>/dev/null
# Rate limit headers
grep -rE "X-RateLimit|RateLimit-|rateLimit.*header" src/ lib/ app/ 2>/dev/null
- Check rate limiter error handling:
# Custom error handlers for rate limiting
grep -rE "onLimitReached|handler.*rate|limitHandler|exceeded" src/ lib/ app/ 2>/dev/null
# Error response format
grep -rE "res\.status\(429\)|response.*429|HttpStatus.*429" src/ lib/ app/ 2>/dev/null
- Actually test the rate limit (rigorous verification):
# If dev server is running, attempt to trigger rate limit
# This is a manual step - run in dev environment only
# Example: rapid requests to trigger limit
# for i in {1..100}; do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/endpoint; done | sort | uniq -c
# Check the response when limit is hit
# curl -v http://localhost:3000/api/endpoint (after triggering limit)
Ask user:
- "What happens when a client hits the rate limit?"
- "Have you tested hitting the rate limit in dev?"
- "Does the response include retry information?"
Cross-reference with:
- RATE-001 (rate limiting configured)
- RATE-003 (documentation includes error responses)
- MON-003 (HTTP logging - 429s should be logged)
Pass criteria:
- Returns 429 Too Many Requests status code
- Response body explains the limit was hit
- Application doesn't crash or return 500
- Retry-After header present (nice-to-have)
Fail criteria:
- Returns 500 or generic error when limit hit
- Application crashes under rate limiting
- No indication client was rate limited
- Response leaks internal implementation details
Evidence to capture:
- Actual 429 response (test in dev)
- Response body content
- Headers included (Retry-After, X-RateLimit-*)
- How rate limit errors are logged