Skip to main content

Drift Detection

Architecture drift is the gradual divergence between your intended design and what the code actually does. Anvil tracks drift by comparing dependency snapshots over time.

Prerequisites

  • Anvil initialised with architecture boundaries configured
  • At least one successful anvil check --all run

1. Capture a Baseline Snapshot

anvil drift snapshot --name baseline
Capturing snapshot: baseline
Modules: 4
Edges: 12
Files: 28

Snapshot saved to .anvil/snapshots/baseline.json

A snapshot records every module and every dependency edge at a point in time.

2. Inspect the Snapshot

anvil drift show baseline
Snapshot: baseline
Captured: 2025-06-15T10:32:00Z

Modules:
presentation (12 files)
business (8 files)
data (5 files)
shared (3 files)

Dependency edges:
presentation -> business (6 imports)
presentation -> shared (2 imports)
business -> data (4 imports)
business -> shared (3 imports)
data -> shared (1 import)

Total edges: 16

3. Make Changes

Work on your codebase as normal. Over days or weeks, new imports get added, modules grow, and the dependency graph shifts.

For this tutorial, suppose you add a utility that the API layer imports directly from the data layer -- a boundary violation that was suppressed because of a deadline.

4. Capture a New Snapshot

anvil drift snapshot --name after-changes
Capturing snapshot: after-changes
Modules: 4
Edges: 14
Files: 31

Snapshot saved to .anvil/snapshots/after-changes.json

5. Compare Snapshots

anvil drift compare baseline after-changes
Drift Report: baseline -> after-changes

New edges:
+ presentation -> data (2 imports) [VIOLATION]
+ data -> business (1 import) [VIOLATION]

Removed edges:
- business -> shared (1 import removed, 2 remaining)

Summary:
New edges: +3
Removed edges: -1
Net drift: +2
Violations: 2

The report highlights exactly which new dependency edges appeared and whether they violate your architecture rules.

6. Set a Drift Budget

Add a drift budget to .anvilrc to fail CI when drift exceeds a threshold:

{
"drift": {
"budget": {
"maxNewEdges": 5,
"maxViolations": 0
},
"baselineSnapshot": "baseline"
}
}
OptionDescription
maxNewEdgesMaximum allowed new dependency edges before failing
maxViolationsMaximum allowed new boundary violations (0 = strict)
baselineSnapshotName of the snapshot to compare against

With maxViolations: 0, any new boundary-crossing edge fails the check:

anvil check --all
Checking drift...
2 new violations since baseline (budget: 0)

Drift budget exceeded.
Update the baseline periodically as your architecture evolves. Run

anvil drift snapshot --name baseline --overwrite after a planned refactor to reset the reference point. :::

Workflow Tips

  • Capture snapshots at release boundaries -- tag them with version numbers
  • Review drift reports in PRs -- the CI integration can post drift summaries as PR comments
  • Use drift budgets as guardrails -- allow some flexibility for active development, tighten for stable modules

Next: CI Integration