Add a per-user rate limit to the to-do list API

What does this MR do and why?

Adds a configurable per-user rate limit to GET /api/v4/todos (300 requests per minute by default), behind the todos_list_api_rate_limit feature flag (gitlab_com_derisk, disabled by default).

Listing to-do items renders the full target entity for each item. For merge requests that includes detailed_merge_status, which runs the mergeability checks, so a page of merge request to-do items can take seconds. The only limit today is the generic authenticated API throttle, which isn't sized for an endpoint this expensive. 300 per minute sits well above normal use, including CLI and integration polling.

  • New todos_list_api_limit application setting in the rate_limits JSONB column (default 300, 0 disables the limit), settable through the application settings API. No migration needed.
  • New todos_list_api key in the labkit rate limit registry (limit_todos_list_api_by_user, per user, per minute), reading its limit from that setting, following the Gitlab::ApplicationRateLimiter guidelines.
  • GET /todos checks it when the flag is enabled for the current user, and returns 429 with Retry-After when the limit is exceeded. The check runs before any to-do work.
  • Documented in the API and Rails console rate limits list and the application settings API, as disabled by default. No changelog entry while the flag is off.

References

Screenshots or screen recordings

Not applicable, no UI change.

How to set up and validate locally

  1. In the Rails console, enable the flag for your user:
    Feature.enable(:todos_list_api_rate_limit, User.find_by_username('root'))
  2. Lower the limit for testing:
    ApplicationSetting.current.update!(todos_list_api_limit: 3)
  3. Call the endpoint repeatedly with a personal access token:
    for i in $(seq 1 5); do curl -s -o /dev/null -w "%{http_code}\n" --header "PRIVATE-TOKEN: <token>" "http://gdk.test:3000/api/v4/todos"; done
  4. After the limit is reached, requests return 429 with a Retry-After header and RateLimit-Name: todos_list_api. With the flag disabled, or with todos_list_api_limit set to 0, all requests return 200.

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.

Edited by Mario Celi

Merge request reports

Loading
Loading