Skip to content

Draft: Approval cache

What does this MR do and why?

This MR implements an approval caching system for GitLab merge requests to improve performance by reducing expensive approval state calculations that occur during merge request evaluations.

Related to: https://gitlab.com/gitlab-com/create-stage/code-review-be/-/issues/176#note_2441965072

Problem

Currently, every time a merge request's approval state needs to be checked (during mergeability checks, UI rendering, etc.), the system performs expensive database queries to calculate whether the MR is approved. This involves:

  • Querying approval rules and their associated users/groups
  • Checking user permissions and group memberships
  • Evaluating complex approval logic

These calculations can be slow and resource-intensive, especially for merge requests with complex approval requirements.

Solution

This MR introduces a Redis-based caching layer that:

  1. Caches approval state calculations - Stores the result of expensive approval state computations
  2. Implements smart cache invalidation - Uses timestamp-based tracking to invalidate cache only when approval-affecting changes occur
  3. Provides graceful fallback - Falls back to direct calculation if cache fails or is unavailable

Key Components

  • Approvals::ApprovalCacheable concern - Adds timestamp tracking to models that affect approval state (groups, users, approval rules, etc.)
  • Approvals::CacheService - Main service for fetching cached approval states or calculating and caching new ones
  • Approvals::RelationTracker - Tracks all entities that can affect a merge request's approval state and manages cache invalidation keys
  • Approvals::StateCalculator - Performs the actual approval state calculation when cache misses occur
  • Approvals::CacheMetrics - Provides observability into cache performance
  • Integration with CheckApprovedService - Updates merge request approval checks to use the cache with feature flag control

How it works

  1. When approval state is requested, the system checks if valid cached data exists
  2. Cache validity is determined by comparing timestamps of all related entities (users, groups, approval rules)
  3. If any related entity has been updated since the cache was created, it's considered invalid
  4. On cache miss, the system calculates the approval state and stores it along with relevant entity timestamps
  5. Changes to tracked entities automatically update their timestamps, invalidating dependent caches

Performance Benefits

  • Reduces database load by avoiding repeated expensive approval calculations
  • Improves merge request page load times
  • Scales better with complex approval rule configurations
  • Only recalculates when actual approval-affecting changes occur

Feature Flag

The caching behavior is controlled by the approval_cache feature flag, allowing for safe rollout and easy rollback if needed.

Screenshots or screen recordings

Performance improvements will be measurable through reduced database query times and faster merge request evaluations.

How to set up and validate locally

  1. Enable the feature flag: Feature.enable(:approval_cache)
  2. Create a merge request with approval rules
  3. View the merge request multiple times - subsequent views should use cached data
  4. Make changes to approval rules, users, or groups - cache should invalidate appropriately
  5. Monitor Redis for cache keys under the approval_cache:v1:* namespace

MR acceptance checklist

  • Code review completed
  • Tests added for new functionality
  • Performance impact measured
  • Feature flag documentation updated
  • Cache invalidation scenarios tested
  • Redis memory usage estimated
  • Error handling and fallback behavior verified

Related issues

Edited by Marc Shaw

Merge request reports

Loading