Blast radius
Blast radius is everything that could break if you change one piece of code, including the paths that cross a repository boundary and the ones no test covers.
Blast radius is everything that could break if you change one piece of code. Not just the lines you edit, but every part of the system that depends on them, including the paths that cross a repository boundary and the ones that no test would catch. It is the honest answer to the question you actually ask before you touch anything: what am I about to affect.
The real question before an edit
Changing a line of code is easy. Knowing whether it is safe to change is the hard part, and it is a different question entirely. When an experienced engineer hovers over a function about to be edited, the thought is not “can I write this change.” It is “if I change this, what else moves.” A function is used by other functions. Those are used by others still. A piece of data has a shape that something far away quietly relies on. The edit is one spot. The consequences spread outward from that spot like a shockwave, and the reach of that shockwave is the blast radius.
The term is borrowed on purpose. Detonate something and the damage is not confined to the point of impact; it radiates out to a distance you had better estimate in advance. Software change is the same. The point of impact is the code you edit. The radius is everything that would feel it. Underestimate the radius and you ship a change that looked local and broke something three steps away that you never thought to check.
Transitive callers: the shockwave has depth
The first layer of blast radius is the direct callers: everything that calls the function you are changing. If you change what a function returns, everything that calls it and uses the result is potentially affected. That much is intuitive.
But callers have callers. Suppose function A calls function B, and B calls the function C that you are about to change. If your change to C breaks B, and B is now broken, then A, which relied on B working, is affected too, even though A never mentions C at all. This chaining is called transitive dependence: the effect passes along the chain, step by step, from the thing you changed outward to things that have no direct connection to it whatsoever. The true blast radius is not the one ring of direct callers. It is every ring the shockwave can reach by hopping from caller to caller.
This is exactly the kind of thing a person cannot hold in their head past a step or two. You can remember who calls C. You might remember who calls those. By the third or fourth hop, across dozens of functions, you are guessing, and the places you forget are precisely the places a surprise breakage comes from.
The shockwave crosses repository walls
Now the part that makes blast radius genuinely hard rather than just tedious. The chain of callers does not stop at the edge of the repository you are working in. A service in another repository might call the function you are changing over the network, through an HTTP request or a message on a shared topic. That caller depends on your code just as truly as one in the same file, but the dependence is expressed as a string in a URL or the name of a message channel, not as a call any single-repository tool could follow.
These are cross-service edges, dependencies that leave one repository and land in another, and they are where blast radius most often gets underestimated. You reason carefully about everything inside your own repository, conclude the change is safe, and ship it, and it breaks a service two teams over that was calling the endpoint you just renamed. Nothing in your repository ever pointed at that service. The dependency was real; it simply lived in the gap between the two codebases. A blast radius that stops at the repository wall is not a blast radius. It is a guess with a blind spot built in.
A blast radius that stops at the edge of your own repository is not a smaller answer. It is a wrong one, because the shockwave does not stop there.
The other axis: what has no test
Reach is only half of the question. The other half is protection. A test is code that exercises other code and checks that it behaves as expected; a body of tests is the net that catches you when a change breaks something. So the useful version of blast radius is not just “what depends on this.” It is “what depends on this and is not covered by any test.”
Those two facts intersect to sort the affected code into two very different piles. Something that depends on your change and has a test around it is comparatively safe: break it and the test fails, loudly, before the change ever reaches users. Something that depends on your change and has no test is the dangerous pile. Break it and nothing complains. It ships, and the failure shows up later, in production, far from the edit that caused it, where it is hardest to trace back.
This is the question worth its own name: of everything in the blast radius, which parts are both affected and unguarded. That set is where your attention and your manual checking should go, because that is where a mistake will not be caught for you. A change with a wide reach but full test coverage may be routine. A change with a narrow reach that happens to touch an untested corner can be the risky one. You cannot tell which without holding both facts, dependence and coverage, at the same time.
A concrete case
Put the two axes together on a single edit. You are tightening the function that formats a customer’s mailing address. In your own repository, three functions call it directly, and two of those are reached by a handful of others, so the internal reach is maybe a dozen pieces of code. Of those, most are exercised by tests, but one, an old export routine, is not.
That would be the whole story for a single-repo tool. But the address formatter is also reached over the network: a separate shipping service, in another repository, calls the endpoint that wraps it. That caller has no test on your side at all, and it is invisible to anything that stops at your repository wall. So the true dangerous set for this edit is two items: the old export routine and the shipping service’s call. Everything else is either unaffected or caught by a test. Without both axes and the cross-boundary reach, you would have checked the wrong dozen things and shipped the two that mattered.
Why text search answers this badly
The instinct, faced with “what depends on this,” is to search the codebase for the name. Search finds every place a string of characters appears, and that is not the same as every place that truly depends on the thing. It over-answers and under-answers at the same time, which is the worst of both.
It over-answers because a name is not a relationship. Search for a common function name and you get comments that mention it, unrelated functions that happen to share the name, and the word buried inside longer words. None of those are real dependencies, but they clutter the result and hide the ones that matter. It under-answers because the connections that most need finding are the ones not spelled with the name at all: a call reached through a base type, where the text at the call site names the parent and not the specific version that runs; a cross-service call, where the dependence is a URL string that never contains the function’s name; a coupling that lives only in the shape of some shared data. Search cannot follow a chain of callers even one hop, let alone across a repository boundary, and it has no idea which of the affected pieces are covered by a test. It answers a question about text. Blast radius is a question about structure.
How a resolved graph answers it
The tool that actually fits the question is a graph of resolved relationships: a stored map in which a call is a real edge from caller to callee, an inheritance link connects a base type to the versions that specialize it, and a cross-service link connects a request in one repository to the handler in another. Once those edges exist as facts, blast radius is a walk over the graph rather than a search over text.
You start at the piece you intend to change and follow the caller edges outward, hop by hop, collecting everything the shockwave can reach: direct callers, their callers, and onward, across repository walls wherever a cross-service edge bridges them. That gives you the reach. Then you overlay coverage: for each affected piece, does an edge from a test reach it. That splits the reach into the guarded pile and the unguarded pile. Both answers, dependence and coverage, come from traversing edges the graph already resolved, so the result is complete in a way a text search cannot be and specific in a way it cannot be either.
Koragraph exposes this directly as one of its tools, namedblast_radius. It is one of nine tools the server offers to an AI coding agent, and it is the one built precisely for the question this whole page is about: given a change, what is affected. Because Koragraph resolves calls, inheritance, and cross-service links across many repositories and stores them in a local database that persists across sessions, the walk it performs follows real edges, including the ones that cross a service boundary, rather than matching strings. An agent about to edit your code can ask blast_radius before it touches anything, and get the reach instead of a guess.
There is a second benefit to computing blast radius from a stored graph rather than in your head each time. Consistency. Two engineers eyeballing the same change will produce two different mental lists of what it affects, shaped by which corners of the system each happens to know. A traversal over resolved edges produces the same answer regardless of who asks, and it does not get tired on the fourth hop or forget the repository across the wall. The result is reviewable: you can look at the set it returned and reason about it, instead of trusting that someone remembered everything.
What it still cannot promise
Honesty about limits matters here. A blast radius built from static edges tells you what could be affected, the full set of paths a change might travel. It does not prove that every one of those paths matters on a given run, because whether a particular caller is reached can depend on conditions only known while the program executes. Some connections, especially those built from strings decided at run time, may not be fully recoverable in advance at all. The right way to read a blast radius is as a bounded, honest set of possibilities to check, not a guarantee that each item will break. That is still a large improvement over the alternative, which is a text search that quietly misses the paths crossing a boundary and says nothing at all about which of them a test would catch.
Where this connects
Blast radius is really an application of several ideas at once. Its skeleton is the call graph, the map of what calls what, which is what you walk outward to find transitive callers. Its reach across repositories comes from cross-service edges, the dependencies that leave one repository and land in another. Its ability to be recovered from source at all rests on static analysis, the practice of learning true facts about a program by reading its structure rather than running it. And all of it lives inside the code knowledge graph, the connected map that makes the walk possible in the first place. Read those to see the machinery; come back here to see what it is for.
Connected concepts
Where this sits
