Apply a note edit rate limit to REST, web and GraphQL
What does this MR do and why?
Editing a note has no rate limit, while creating one does, and every edit reprocesses mentions and cross references. This MR adds a notes_update rate limit of 300 requests per minute for each user. It has its own key, so editing and creating notes do not draw from the same budget, and it uses the notes_create_limit_allowlist so one list exempts a user from both limits.
It applies to every user-facing entry point that edits a note:
PUT .../notes/:note_idandPUT .../discussions/:discussion_id/notes/:note_id(REST)PUT .../work_items/:work_item_iid/notes/:note_id(REST)NotesActions#update(web note edit, including snippets)- the GraphQL
updateNote,updateImageDiffNoteandrepositionImageDiffNotemutations
REST and GraphQL charge the limit before the note is looked up, like the create endpoints. The web action charges it after the user is authorized to edit the note. Requests over the limit return 429 Too Many Requests (REST and web) or the same "requested too many times" error that the create mutations return (GraphQL).
The limit ships behind the notes_update_rate_limit feature flag, which is disabled by default so that GitLab.com can enable it gradually and roll it back. The limit is listed with the non-configurable rate limits in the docs. The limit is fixed for now. Whether to make it an application setting depends on the decision in an open proposal on rate limiter endpoint grouping, so that is not part of this MR.
How to set up and validate locally
-
Enable the feature flag, which is off by default:
bundle exec rails runner 'Feature.enable(:notes_update_rate_limit)' -
Create a personal access token with the
apiscope and note one of your notes (project ID, issue IID, note ID). -
Send more edits than the limit within a minute:
URL="http://gdk.test:8080/api/v4/projects/$PROJECT_ID/issues/$ISSUE_IID/notes/$NOTE_ID" # Send 310 edits, 40 at a time, then count the responses by HTTP status seq 1 310 | xargs -P 40 -I{} \ curl -s -o /dev/null -w "%{http_code}\n" -X PUT \ -H "PRIVATE-TOKEN: $TOKEN" --data-urlencode "body=edit {}" "$URL" | sort | uniq -cAbout 300 requests return 200 and the rest return 429.
-
Add your username to the
notes_create_limit_allowlistsetting, wait a minute, and run the command again. Every request returns 200.
References
Relates to https://gitlab.com/gitlab-org/gitlab/-/work_items/634354
Rollout issue: #638521
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.