# How OpenCodeReview Handles Large Changesets: Scalable Architecture Explained

> Discover how OpenCodeReview scales to handle large changesets by batching, parallel processing, and streaming LLM responses. Learn about its efficient architecture.

- Repository: [Alibaba/open-code-review](https://github.com/alibaba/open-code-review)
- Tags: architecture
- Published: 2026-08-06

---

**OpenCodeReview (OCR) processes massive pull requests by breaking changesets into deterministic batches, running parallel workers, and streaming LLM responses to control memory usage.**

When reviewing pull requests with thousands of files or megabytes of changes, most code review tools struggle with memory exhaustion, timeouts, or non-deterministic output. OpenCodeReview, Alibaba's open-source code review agent, solves this through a multi-layered approach that normalizes input, batches files intelligently, and persists intermediate results. This article examines how the OCR codebase in `alibaba/open-code-review` scales to enterprise-sized changesets.

## Normalizing Input: The Unified Diff Model

Every input to OCR—whether a git diff or a full file scan—converts to a consistent internal representation. In [`internal/model/diff.go`](https://github.com/alibaba/open-code-review/blob/main/internal/model/diff.go), the `Diff` struct encapsulates all necessary metadata:

```go
type Diff struct {
    OldPath        string `json:"old_path"`
    NewPath        string `json:"new_path"`
    Diff           string `json:"diff"`
    NewFileContent string `json:"new_file_content"`
    // ...
}

```

This normalization ensures the downstream pipeline remains identical regardless of input source. For scenarios without a unified diff—such as scanning entire files—OCR creates synthetic `Diff` objects from `ScanItem` structs defined in [`internal/model/scan.go`](https://github.com/alibaba/open-code-review/blob/main/internal/model/scan.go).

## Full-Scan Mode for Diff-Heavy Changesets

When a changeset exceeds configurable thresholds for file count or diff size, OCR switches to **full-scan mode**. Rather than attempting to parse unwieldy diffs, this mode reads each file's complete content:

```go
// ScanItem carries full file content when diff parsing is impractical
type ScanItem struct {
    Path    string
    Content string // Full file contents
    // Diff field intentionally empty in scan mode
}

```

According to the source in [`internal/model/scan.go`](https://github.com/alibaba/open-code-review/blob/main/internal/model/scan.go):

> "The Diff field stays empty since scan mode has no unified diff; NewFileContent carries the whole file so resolver.resolveFromFileContent can still find the source lines."

This design preserves line number resolution capabilities without requiring diff parsing, enabling OCR to handle PRs with extensive binary modifications or generated code where diffs become meaningless noise.

## Batching Strategy: Grouping Files for Efficient Processing

The core scaling mechanism lives in [`internal/scan/batch.go`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/batch.go). OCR supports three deterministic batching strategies controlled by the `BatchStrategy` type:

```go
type BatchStrategy string

const (
    BatchNone        BatchStrategy = "none"         // One file per batch
    BatchByLanguage  BatchStrategy = "by-language"  // Group by extension
    BatchByDirectory BatchStrategy = "by-directory" // Group by top-level dir
)

```

- **BatchNone**: Each file becomes its own batch—simplest, highest parallelization
- **BatchByLanguage**: Groups `.go`, `.py`, `.java` files separately—useful when language-specific context matters
- **BatchByDirectory**: Colocates files from `src/auth/`, `src/api/`, etc.—preserves architectural boundaries

After grouping, files within each group are sliced into **chunks** of configurable `BatchSize` (default: 10). The `groupBatches` and `batchKeyFunc` implementations in [`batch.go`](https://github.com/alibaba/open-code-review/blob/main/batch.go) ensure deterministic ordering by sorting group keys with `sort.Strings(keys)`, making outputs reproducible and cacheable.

## Parallel Dispatch with Background Persistence

Each batch executes through independent workers spawned by the scan dispatcher in [`internal/scan/agent.go`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/agent.go). This architecture delivers two critical benefits for large changesets:

1. **Multi-core utilization**: Workers run identical pipelines (parse → LLM request → comment generation) on disjoint file subsets
2. **Latency control**: Review time scales with batch size rather than total PR size

For resilience, OCR implements a **background file mechanism** in [`cmd/opencodereview/background_file.go`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/background_file.go). Intermediate LLM responses serialize to disk, enabling:
- Crash recovery without reprocessing completed batches
- CLI resume capability for interrupted long-running reviews
- Idempotent re-execution of partially completed reviews

## Streaming LLM Responses to Constrain Memory

The LLM client in [`internal/llm/client.go`](https://github.com/alibaba/open-code-review/blob/main/internal/llm/client.go) processes responses as **streaming chunks** rather than buffering complete replies. This approach:

- Eliminates memory spikes from large generated reviews
- Validates usage limits incrementally
- Merges partial responses into final batch results

Memory pressure stays bounded regardless of response length because the full output never materializes in memory simultaneously.

## Deterministic Output and Intelligent Caching

OCR guarantees reproducible results through:
- **Sorted batch keys**: `sort.Strings(keys)` ensures consistent processing order
- **Content-addressed caching**: Batch results cache to `.ocr/cache/` using hashes of file lists and contents
- **Independent batch processing**: No cross-batch state dependencies

Re-running the same PR becomes nearly instant when cached results exist, supporting iterative review workflows and CI/CD integration.

## CLI Controls for Tuning Large Changeset Handling

Users tune OCR's scaling behavior through flags defined in [`cmd/opencodereview/flags.go`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/flags.go):

| Flag | Purpose | Default |
|------|---------|---------|
| `--batch-size <N>` | Files per chunk | 10 |
| `--batch-strategy <mode>` | Grouping policy | `none` |
| `--scan` | Force full-scan mode | off |

```bash

# Review a 500-file PR grouped by language, 20 files per batch

ocr review \
    --repo https://github.com/example/monorepo \
    --pr 456 \
    --batch-strategy by-language \
    --batch-size 20

# Force full-scan when diff contains many binary files

ocr review --repo . --scan --batch-strategy by-directory

```

## Programmatic Batch Control

For custom integrations, the batch engine exposes clean APIs:

```go
import (
    "github.com/alibaba/open-code-review/internal/model"
    "github.com/alibaba/open-code-review/internal/scan"
)

func reviewLargePR(items []model.ScanItem) [][]model.ScanItem {
    // Group by directory, 15 files per batch
    return scan.GroupBatches(items, scan.BatchByDirectory, 15)
}

```

## Key Source Files

Understanding OCR's large-changeset handling requires familiarity with these components:

- [`internal/model/diff.go`](https://github.com/alibaba/open-code-review/blob/main/internal/model/diff.go) — Core `Diff` struct definition
- [`internal/model/scan.go`](https://github.com/alibaba/open-code-review/blob/main/internal/model/scan.go) — `ScanItem` and synthetic diff generation
- [`internal/scan/batch.go`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/batch.go) — Batching strategies and chunking logic
- [`internal/scan/agent.go`](https://github.com/alibaba/open-code-review/blob/main/internal/scan/agent.go) — Worker dispatch and parallel processing
- [`cmd/opencodereview/background_file.go`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/background_file.go) — Intermediate result persistence
- [`internal/llm/client.go`](https://github.com/alibaba/open-code-review/blob/main/internal/llm/client.go) — Streaming response handling
- [`cmd/opencodereview/flags.go`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/flags.go) — CLI configuration for batch controls

## Summary

OpenCodeReview handles large changesets through seven coordinated mechanisms:

- **Input normalization**: All sources convert to uniform `Diff` structures
- **Full-scan fallback**: Bypasses problematic diffs for massive changes
- **Configurable batching**: Groups files by language, directory, or individually
- **Deterministic chunking**: Fixed-size batches with sorted, reproducible ordering
- **Parallel workers**: Multi-core processing of independent batches
- **Background persistence**: Disk-based crash recovery and resume capability
- **Streaming LLM I/O**: Bounded memory regardless of response size

These techniques enable OCR to review PRs with thousands of files predictably, without memory exhaustion or timeout failures.

## Frequently Asked Questions

### What is the maximum PR size OpenCodeReview can handle?

There is no hard limit imposed by OCR's architecture. The tool processes PRs with thousands of files by batching them into manageable chunks. Practical limits depend on available disk space for background files and LLM API rate limits rather than OCR's internal memory constraints.

### How does batching affect review quality?

Batching preserves quality through deterministic grouping strategies. Files in the same batch share context naturally—either linguistic similarity (`by-language`) or architectural proximity (`by-directory`). The `none` strategy maximizes parallelization but may miss cross-file patterns; larger batch sizes increase context at the cost of slower per-batch processing.

### Can I resume a review if the process crashes?

Yes. OCR's background file mechanism in [`cmd/opencodereview/background_file.go`](https://github.com/alibaba/open-code-review/blob/main/cmd/opencodereview/background_file.go) persists intermediate LLM responses to disk. When restarted, the CLI detects completed batches in `.ocr/cache/` and skips already-processed chunks, continuing from the point of interruption.

### When should I use full-scan mode versus diff mode?

Use full-scan mode (`--scan`) when: diffs exceed reasonable parsing time, the repository contains many binary or generated files, or you need consistent line number resolution regardless of diff complexity. Diff mode is preferred for smaller, source-focused changesets where incremental review history matters.