May 19, 2026
The architecture review checklist: how to catch structural risk in a PR, by hand
A practical, tool-agnostic checklist for reviewing pull requests for architectural risk: new dependency directions, blast radius, layer skips, cycles, and coupling drift. Plus the free tools that help, and the honest math on what it costs.
Most code review checklists cover correctness, tests, and style. Almost none cover the thing that actually degrades codebases over years: structure. Which new dependencies a PR creates, what they point at, and what that does to the shape of the system.
This post is the checklist we wish every team had. It’s tool-agnostic and fully manual: everything below can be done with an IDE, grep, and patience. (We’ll be honest at the end about how much patience.)
The checklist
Work through this on any PR that adds imports, moves code, or touches shared components, which, in practice, is most nontrivial PRs:
Structural review, step by step
1. List the components, not the files
From the diff, write down every class/module touched and every new import. You're building a mental mini-graph: nodes and new edges. Files are how the diff is displayed; components are what the architecture is made of.
2. Check each new edge's direction
For every new import: which package depends on which, and is that direction consistent with your layering? Core importing from a plugin, domain importing from infrastructure, shared utils importing from a feature: each is one line in the diff and a boundary inversion in the graph.
3. Check for layer skips
Even when the direction is right, does the edge jump past an intermediate layer (controller straight to repository, bypassing the service)? Skips are how layers erode; each one makes the next easier to justify.
4. Measure the blast radius of modified contracts
For every changed public interface, base class, or widely-used component: find-usages and count. A three-line change to something with 24 dependents is a bigger event than a 500-line change to a leaf. Say the number out loud in the review.
5. Hunt for cycles, including near-cycles
For each new edge A → B, ask: is there any existing path from B back to A? If yes, this PR closes a cycle. If a path gets within one hop, it plants a near-cycle seed. Flag it now while the fix is one comment.
6. Watch coupling drift on hot nodes
Is this PR adding outgoing dependencies to a component that many things already depend on? Delta × afferent coupling is the risk number. A +3 on a hub is worth a conversation; a +3 on a leaf is not.
7. Ask the trend question
Is this the second or third PR nudging the same component in the same direction? One convenient import is an exception; three are a new architecture nobody decided on. This is the check that catches drift, and the one that requires memory.
Steps 1–3 need only the diff and the repo. Steps 4–7 need the rest of the graph, which is exactly why they're the ones that get skipped under deadline.
The cheat sheet
The compressed version, for pinning next to your review queue:
Signal → question → red flag
| You see in the diff | You ask | Red flag |
|---|---|---|
| A new import | Which way does this edge point? | Toward a plugin, a feature, or anything "above" the importer |
| A moved class | What do its dependents import now? | Dependents now reach across a boundary to follow it |
| A changed interface or base class | How many dependents? (Count them.) | Dozens of dependents on a "trivial" change |
| A new edge A → B | Does any path lead from B back to A? | Yes (cycle), or almost (near-cycle) |
| Another util added to a "utils" module | What's this module's coupling trend? | A hub steadily gaining edges in both directions |
| A tiny diff on a core component | What's the blast radius? | Small diffs on high-dependency nodes hide the biggest surprises |
Every red flag in this table corresponds to a real finding from our analysis of merged refactor PRs: contract changes with dozens of dependents, first-ever boundary crossings, a package cycle born in a clean-looking diff.
Free tools that help
You can automate slices of this today, no budget required:
The DIY toolbox
| Ecosystem | See the graph / find cycles | Enforce known boundaries |
|---|---|---|
| Java / JVM | jdeps (ships with the JDK) | ArchUnit rules in your test suite |
| JS / TypeScript | madge --circular | dependency-cruiser |
| Python | pydeps | import-linter contracts |
| .NET | IDE dependency diagrams | NetArchTest |
Rule-enforcement tools are genuinely worth adopting; they lock in the boundaries you already know about. Their limit: someone has to write each rule in advance, and they check rules, not trends. Steps 6 and 7 remain manual.
The honest math
Now the part most checklist posts skip. Suppose a competent structural pass (steps 1 through 7, done honestly) takes 15 to 30 minutes on a nontrivial PR. Simple arithmetic, at 20 minutes average:
Manual structural review, minutes per day
Arithmetic, not a study: PR count × 20 minutes. Three hundred minutes is five senior-engineer hours per day, and it lands on your most senior people, because they're the only ones holding enough of the graph in their heads to do steps 4–7 at all.
This is why “we’ll just review more carefully” fails as a strategy at AI-era shipping volume. The checklist is sound; the budget doesn’t exist. Teams don’t skip structural review because they don’t care. They skip it because it’s the only review activity whose cost scales with the size of the codebase rather than the size of the diff.
Striff automates steps 1 through 7 on every pull request. It parses both sides of the PR into a dependency graph, computes the deltas, checks directions, skips, cycles, and blast radius, and posts only what’s worth a reviewer’s attention. The judgment stays yours; the 20 minutes don’t. Install the browser extension and run the checklist on your next PR in seconds.