Also called Impact radius, Change impact, Impact analysis
How blast radius is measured
The word has two common uses. In infrastructure and SRE work, blast radius is the share of users, regions or services a failure or bad deploy can take down, and designs such as cells and staged rollouts exist to shrink it. For code changes, which is the focus here, you measure it by walking dependencies outward from what changed.
- List the changed functions or files.
- Find everything that calls or imports them (depth 1).
- Find everything that calls or imports those (depth 2), and continue to a depth limit.
- Add files that historically change in the same commits (see temporal coupling), and the tests that reach any of it.
A worked example. A diff changes parse_amount() in billing/money.py:
| Depth | What is reached | Count |
|---|---|---|
| 0 | parse_amount() itself | 1 function |
| 1 | invoice.py, refund.py, export.py call it | 3 files |
| 2 | api/checkout.py, api/admin.py import the depth-1 files | 2 files |
| Co-change | billing/money_test_data.json usually changes with it | 1 file |
The blast radius is 6 files beyond the edit, and the number that matters is how many of them have no test. A change to a private helper nobody imports has a radius near zero; a change to a function imported by 200 files has a large one even when the diff is one line.
Static graphs undercount reach through reflection, dynamic dispatch and runtime wiring, so treat the result as a floor.
Why blast radius matters
Diff size is a poor guide to danger. A one-line edit to a shared helper can break more than a 500-line change to a leaf script. Blast radius tells a reviewer where to look and tells an author which tests to run, instead of running everything or trusting the diff's size. It also shows when a change should be split: if the radius covers unrelated areas, two pull requests are easier to review and easier to revert.
It is one input to change risk, which adds the history of the touched files. Radius says what could be affected; history says whether these files have broken before.
How to measure blast radius yourself
You can get a first answer with free tools:
# Who imports this module (rough, text-based)
grep -rn "from billing.money import\|import billing.money" src | wc -l
# Python import graph, by module
pydeps billing --show-deps
# JavaScript/TypeScript: what depends on a file
npx madge --depends src/billing/money.ts srcgrep misses re-exports and aliased imports, and pydeps and madge work at module level, not function level. For function-level callers in a typed language, your IDE's "find usages" is usually more accurate than any of these. Co-change is not in these tools: for that, count shared commits with git log --name-only -- <file> and compare. See the dependency graph and call graph entries for how the underlying data is built, and the PR risk and blast radius tools roundup for tools that compute it.
How repowise measures blast radius
repowise builds the dependency and call graph, reads git history, and combines them for a change. Everything is deterministic, with no LLM calls.
get_riskin PR mode (passchanged_files) returns a blast-radius block: direct risk per changed file, transitive affected files found by walking importers up to a depth limit (3 by default in the analyzer), co-change partners the diff left out, and the tests to run. The walk records which file each transitive file was reached through.get_change_riskscores a commit, range or uncommitted work and lists missing co-change files and tests that reach the diff. See change risk.- The PR bot posts the result on pull requests. It is GitHub only.
get_blast_radiusis an MCP tool available in workspaces (enable it with--tools +get_blast_radiusormcp.tools: ["+get_blast_radius"]). It traverses the cross-repo graph and returns impacted services with a score and distance, ranking contract and package dependencies above co-change.
The same ideas are described in the change risk docs and the get_risk reference.