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 --allrun
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"
}
}
| Option | Description |
|---|---|
maxNewEdges | Maximum allowed new dependency edges before failing |
maxViolations | Maximum allowed new boundary violations (0 = strict) |
baselineSnapshot | Name 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.
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