Design a Code Review System
A full Staff-level walkthrough of a Critique-style code review system serving 100K+ developers and 50K changelists a day — rendering diffs for thousand-file CLs in under two seconds while keeping review state strongly consistent. It trades diff-compute cost against latency with a four-tier cache, resolves approvals from path-based OWNERS files, and anchors comments so they survive patchset uploads and rebases. Follow it top to bottom, or jump to any step.
Requirements
Functional Requirements
- Create changelists (CLs): Developers submit code changes for review, including diffs against a base revision
- Diff computation and display: Show side-by-side or unified diffs with syntax highlighting
- Inline comments: Reviewers leave comments on specific lines, ranges, or files
- Comment threads: Support threaded discussions with replies, resolution status
- Review workflow: Request review, LGTM (approve), Request Changes, Submit (merge)
- Multi-reviewer support: Multiple reviewers with different roles (owner, reviewer, CC)
- Approval rules: Configurable per-directory/team (e.g., requires 2 LGTMs from owners)
- CI/CD integration: Trigger automated builds/tests, display results on the CL
- Search: Search CLs by author, reviewer, status, file path, date range, content
- Code navigation: Click-through to definitions, references within the diff view
- Review analytics: Time-to-review, review load per person, approval rates
- Notifications: Email, in-app notifications for CL updates, comments, approvals
Non-Functional Requirements
- Low latency: Diff rendering < 2 seconds even for large CLs (1000+ files)
- High availability: 99.99% uptime (code review is on the critical path)
- Scalability: Support 100K+ active developers, 50K+ CLs/day
- Consistency: Strong consistency for review state (no lost comments or approvals)
- Real-time updates: Collaborators see new comments within seconds (push-based)
- Large diff support: Handle CLs with thousands of files and millions of lines
Constraints
- Must integrate with existing VCS (Git, Piper/CitC at Google)
- Must support monorepo (single repository with millions of files, billions of lines)
- Diffs are against a snapshot, not necessarily HEAD (base may be stale)
- Comment positions must survive rebases (line positions shift)
Back-of-envelope estimation
Users and Activity
- Active developers: 100,000
- CLs created per day: 50,000
- Average reviews per CL: 3 (iterations/patchsets)
- Comments per CL: 10
- Average files per CL: 15
- Average diff size per file: 100 lines changed
Traffic
- Page views (CL view, diff view): 2 million/day
- QPS for page loads: 2M / 86400 ~= 23 QPS average, peak ~100 QPS
- Comment writes: 500K/day ~= 6 QPS average
- CI status updates: 200K/day ~= 2 QPS
- Search queries: 100K/day ~= 1 QPS
- Notification events: 1M/day
Storage
- Per CL metadata: ~5 KB (description, reviewers, status, timestamps)
- Per comment: ~500 bytes (author, line, text, timestamp, thread)
- Per diff (precomputed): ~50 KB average per file, 15 files = 750 KB per CL
- Daily storage: 50K CLs (5 KB + 10 500B + 750 KB) = ~40 GB/day
- Annual storage: ~15 TB
- File content (stored in VCS, not duplicated): petabytes (monorepo)
Compute
- Diff computation: Myers algorithm O(ND) where N = file length, D = edit distance
- Average file: 500 lines, 50 changes -> ~25,000 operations
- 50K CLs * 15 files = 750K diffs/day
- Peak: ~30 diffs/second
- Syntax highlighting: ~10ms per file (regex-based lexer)
API design
Changelist Management
Diff Retrieval
Comments
Review Actions
Search
Data model
Core Tables
Diff Storage
Storage Choice Rationale
High-level architecture
Request Flow: Viewing a CL Diff
Request Flow: Submitting (Merging) a CL
Deep dives
WHERE STAFF IS WONDeep Dive 1: Diff Computation and Large CL Handling
Problem: Computing and rendering diffs must be fast even for large changelists (1000+ files, files with thousands of lines).
Diff Algorithm Selection:
Large CL Optimization:
Comment Position Tracking Across Patchsets:
Deep Dive 2: Approval Workflow and OWNERS System
Problem: In a monorepo, different parts of the codebase have different owners. A CL touching files in multiple directories may need approval from multiple owners.
OWNERS File System:
Approval Resolution Algorithm:
Approval Caching:
Deep Dive 3: CI/CD Integration and Presubmit Checks
Problem: Every CL must pass automated checks before submission. These checks range from seconds (lint) to hours (full integration tests). How do we design for both speed and thoroughness?
Check Categories and Timing:
CI Integration Architecture:
Incremental Checks (critical for developer productivity):
Pre-submit Queue (for submit-time checks):
Bottlenecks and Tradeoffs
Bottleneck 1: Monorepo Scale
- Problem: In a monorepo with billions of lines, even listing files in a directory can be slow.
- Solution:
- Virtual filesystem (e.g., FUSE mount) that lazily fetches file content
- File-level caching with content-addressed storage
- Diff computation works on file hashes first; identical files (same hash) = no diff
- Sparse checkout: developer's workspace only contains relevant files
Bottleneck 2: Real-Time Collaboration
- Problem: Multiple reviewers commenting simultaneously; they should see each other's comments in real-time.
- Solution:
- WebSocket connections from all viewers of a CL
- On comment post: write to DB, publish to Redis Pub/Sub channel for that CL
- All connected clients receive the update within ~100ms
- Conflict resolution: comments are append-only, no conflicts possible
- Presence: show who is currently viewing the CL (via WebSocket heartbeat)
Bottleneck 3: Search Performance
- Problem: Searching across millions of CLs by content, author, file path, date range.
- Solution:
- Elasticsearch index with fields: title, description, author, reviewer, file_paths, status, labels, date
- Full-text search on CL descriptions and comments
- Code search (within diffs) is more expensive: index only file paths and metadata, not diff content
- For code content search: integrate with separate code search system (like Google Code Search)
Bottleneck 4: Notification Fatigue
- Problem: Active developers receive hundreds of notifications per day, leading to alert fatigue.
- Solution:
- Intelligent batching: group notifications within 5-minute windows
- Priority levels: blocking comments = immediate; FYI comments = batched
- Muting: allow muting CLs, specific threads, or all-but-my-CLs
- Smart digest: daily summary of pending reviews, ordered by urgency
- ML-based: predict which CLs need attention based on staleness, author patterns
Bottleneck 5: Stale Diffs After Rebase
- Problem: Developer rebases CL onto latest HEAD. All patchset diffs must be recomputed against the new base.
- Solution:
- Don't recompute diffs for old patchsets (they're historical)
- Only compute diff for latest patchset against new base
- Show "interdiff" between patchsets (PS1 vs PS2) regardless of base changes
- This preserves review context: reviewer can see "what changed since my last review"
Monitoring and Observability
Key Design Decisions Summary
Rubric — Senior vs Staff
Want more breakdowns like this?
Join free early access for upcoming RAG, LLM eval, agents, and AI infrastructure walkthroughs.