Return Retry-After header when rate limit is hit
What does this MR do and why?
This MR improves the API rate limiting behavior by returning a proper Retry-After header when rate limits are hit. Previously, the API::Helpers::RateLimiter#check_rate_limit! method was calling render_api_error! directly, missing the opportunity to provide clients with timing information about when they can retry their requests.
Changes made:
- Replace render_api_error!withtoo_many_requests!helper method in rate limiter
- Add Retry-Afterheader with the configured rate limit interval
- Make Gitlab::ApplicationRateLimiter.intervalmethod public to support this functionality
- Add comprehensive test coverage for the new behavior
Why this matters:
- Clients like GitLab Runner can now know exactly how long to wait before retrying
- Reduces unnecessary retry attempts that would immediately hit the rate limit again
- Follows HTTP standards for rate limiting (RFC 6585)
- Improves overall API user experience
Changelog: fixed
References
- Closes #572559 (closed)
- Related to gitlab-com/gl-infra/production-engineering#25372
Screenshots or screen recordings
This is a backend API change with no UI impact. The improvement is visible in HTTP response headers:
Before:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
{"message": "This endpoint has been requested too many times. Try again later."}After:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 600
{"message": "This endpoint has been requested too many times. Try again later."}How to set up and validate locally
- 
Set up a rate limit for testing in Rails console: # Enable a low rate limit for testing stub_application_setting(throttle_authenticated_api_enabled: true) stub_application_setting(throttle_authenticated_api_requests_per_period: 1) stub_application_setting(throttle_authenticated_api_period_in_seconds: 60)
- 
Make API requests to trigger the rate limit: # First request should succeed curl -H "Authorization: Bearer YOUR_TOKEN" "http://localhost:3000/api/v4/projects" # Second request should return 429 with Retry-After header curl -I -H "Authorization: Bearer YOUR_TOKEN" "http://localhost:3000/api/v4/projects"
- 
Verify the Retry-Afterheader is present in the 429 response
- 
Run the new integration tests: bundle exec rspec spec/lib/api/helpers/rate_limiter_integration_spec.rb bundle exec rspec spec/lib/api/helpers/rate_limiter_spec.rb
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
- 
Functionality: Improves API rate limiting by providing proper Retry-Afterheaders
- 
Performance: No performance impact - only changes response headers 
- 
Reliability: Comprehensive test coverage added for new functionality 
- 
Security: No security implications - maintains existing rate limiting behavior 
- 
Maintainability: Code is cleaner by reusing existing too_many_requests!helper
- 
Documentation: No documentation changes needed - this is an HTTP standard header 
- 
Testing: Added integration tests and updated unit tests