You're six months into a project. The codebase that started clean now has database calls in the domain layer, circular dependencies nobody remembers adding, and a "quick fix" that coupled two services together. You know the architecture drifted — but when? How much? Is it getting worse?
Pacta answers these questions. It versions your architecture like Git versions your code, so you can see exactly how your system evolves over time.
Install Pacta:
pip install pactaCreate architecture.yml to describe your system's layers:
version: 1
system:
id: myapp
name: My Application
containers:
backend:
code:
roots: [src]
layers:
domain:
patterns: [src/domain/**]
application:
patterns: [src/application/**]
infra:
patterns: [src/infra/**]Now capture a snapshot:
pacta snapshot save . --model architecture.ymlPacta just analyzed every module and dependency in your codebase and stored a content-addressed snapshot in .pacta/. This snapshot is immutable — a permanent record of your architecture at this moment.
A week passes. Your team ships features, fixes bugs, refactors code. Run another snapshot:
pacta snapshot save . --model architecture.ymlNow you have two points in time. See what changed:
pacta history show --last 5TIMESTAMP SNAPSHOT NODES EDGES VIOLATIONS
2024-01-22 14:30:00 f7a3c2... 48 82 0
2024-01-15 10:00:00 abc123... 45 78 0
Three new modules, four new dependencies. But are things getting better or worse? View the trend:
pacta history trends . --metric edgesEdge Count Trend (5 entries)
============================
82 │ ●
│ ●--------------
79 │ ●----------
│
76 ├●---
└────────────────────────────────
Jan 15 Jan 22
Trend: ↑ Increasing (+6 over period)
First: 76 edges (Jan 15)
Last: 82 edges (Jan 22)
Average: 79 edges
Min: 76, Max: 82
Coupling is climbing. You caught drift early — before it became a problem someone complains about in a retrospective.
Need to share this with the team? Export as an image:
pip install pacta[viz] # one-time install for chart export
pacta history trends . --metric edges --output coupling-trend.pngThis generates a publication-ready chart with trend annotations — drop it into a PR, a Slack thread, or your architecture docs.
You want to protect what you've built. Create rules.pacta.yml:
rule:
id: no_domain_to_infra
name: Domain cannot depend on Infrastructure
severity: error
target: dependency
when:
all:
- from.layer == domain
- to.layer == infra
action: forbid
message: Domain layer must not import from InfrastructureRun a check against your snapshot:
# Option A: Check the snapshot you already have
pacta check . --rules rules.pacta.yml
# Option B: Or do snapshot + check in one step
pacta scan . --model architecture.yml --rules rules.pacta.yml✗ 2 violations (2 error) [2 new]
✗ ERROR [no_domain_to_infra] @ src/domain/user.py:3:1
status: new
Domain layer must not import from Infrastructure
Two violations. But wait — this is a legacy codebase. You can't fix everything today.
Save the current state as a baseline:
# One-step:
pacta scan . --model architecture.yml --rules rules.pacta.yml --save-ref baseline
# Or two-step:
pacta snapshot save . --model architecture.yml --ref baseline
pacta check . --ref baseline --rules rules.pacta.ymlNow future checks compare against this baseline:
pacta check . --rules rules.pacta.yml --baseline baseline
# Or equivalently:
pacta scan . --model architecture.yml --rules rules.pacta.yml --baseline baselineNew violations fail CI. Existing ones are tracked but tolerated. You can pay down debt at your own pace while preventing new debt from accumulating.
A month later, you check progress:
pacta history trends . --metric violationsViolations Trend (8 entries)
============================
12 ├●
│ ●---●
8 │ ●---●
│ ●---●
4 │ ●
└────────────────────────────────
Feb 01 Feb 28
Trend: ↓ Improving (-8 over period)
First: 12 violations (Feb 01)
Last: 4 violations (Feb 28)
Average: 7 violations
Min: 4, Max: 12
You're winning. Export it for the next retro:
pacta history trends . --metric violations --output debt-burndown.pngTraditional architecture tools give you a pass/fail at a point in time. Pacta gives you something different: a versioned history of your architecture that you can query, compare, and trend.
When someone asks "when did our architecture start degrading?" — you have the answer. When a refactor claims to improve coupling — you can measure it. When leadership wants proof that technical debt is being addressed — you have the chart.
Architecture stops being something that "just happens" and becomes something you observe, understand, and control.
Project structure:
myproject/
├── architecture.yml # Layer definitions
├── rules.pacta.yml # Governance rules
├── src/
│ ├── domain/
│ ├── application/
│ └── infra/
└── .pacta/ # Snapshot storage
Next steps:
- CLI Reference — Commands and options
- Architecture Model — Configuration schema
- Rules DSL — Rule conditions
- CI Integration — Automate in your pipeline