Batch authorized projects refresh in IdP group sync
What does this MR do and why?
The Authorization group has been over its weekly error budget three weeks in a row. Nearly all of it comes from background jobs that run longer than their target, and AuthorizedProjectsWorker (recalculates which projects a user can access; 10 second target) is about 77% of it. The background identity-provider group sync (Groups::SyncService) is the largest single trigger: it changes a person's memberships one group at a time, and each change queued its own high-urgency recalculation for the same person. That accounted for 1,239 of about 6,900 over-target runs (about 18%) in the week of 2026-09-20 to 2026-09-27.
Behind the group_sync_single_authorized_projects_refresh feature flag, the sync skips the per-membership recalculation and queues one per person when it finishes. Expected effect is fewer than the original estimate of about 1,090 fewer over-target jobs per week, because only new memberships now move to the low-urgency worker. Changes to existing memberships stay high priority. How many of the 1,239 sync-triggered runs were new memberships versus changes isn't known yet, so it will be re-measured after rollout. That is not enough on its own; the baseline numbers and how to re-measure are in https://gitlab.com/gitlab-org/gitlab/-/work_items/625211.
- The single recalculation is medium priority (low-urgency worker, 300 second target) if the sync only added new memberships. If it removed or changed any existing membership, it is high priority so lost access applies without delay. Any change counts, not only a lower access level, because access levels don't stack (for example, Planner has permissions that Reporter does not), and Minimal Access removes all project access under the group. A sync that changes nothing queues nothing.
- The medium-priority recalculation is queued right away, without the usual one minute delay. SAML sign-in runs this sync, and the person is waiting for access.
- The recalculation is still queued if the sync fails partway, so a removal is never left unapplied. It waits for any surrounding database transaction to commit, and nothing is queued if that transaction rolls back.
- Out of scope: the SCIM API endpoints.
References
- Issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/625211
- Feature flag rollout: #631558
- Epic: https://gitlab.com/groups/gitlab-org/-/work_items/22633
Screenshots or screen recordings
Not applicable: backend-only change with no UI.
How to set up and validate locally
- Run
bin/rspec ee/spec/services/groups/sync_service_spec.rb. Theauthorized projects refreshexamples cover the flag on and off, removals versus additions, a failure partway through the sync, and running inside a transaction.
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.