Impact Analysis: What Happens If We Retire This Application?
Someone in a steering committee asks it almost casually: "Can we just retire the old CRM once the new one is live?" Everyone looks at the architect. The honest answer is never yes or no on the spot — it's "give me a few days to check what depends on it." What follows, in most organizations, is not a query. It's an archaeology project: old diagrams pulled up, integration leads pinged on Slack, a spreadsheet from two reorganizations ago consulted like a religious text. The question is simple. Answering it completely, in a diagram-first world, is not.
This is one of the most common things an architect is asked to produce, and one of the least well served by traditional tooling. Not because the underlying analysis is conceptually hard — it's a well-defined graph traversal problem — but because most architecture tools have nothing to traverse. They have pictures. And a picture only tells you what someone remembered to draw.
What "what breaks" actually means
Before getting to how the analysis works, it's worth being precise about what a complete impact analysis actually has to cover, because the question is usually asked as if it has one answer, and it doesn't. There are at least five layers, and a partial analysis that only covers the first one or two is the most common way retirements go wrong.
- Direct dependents. Anything with a relationship pointing straight at the element in question — an application that calls its API, a report that queries its database, a service that consumes its message queue. This is the layer everyone checks. It's also the layer that's usually visible in at least one diagram, which is exactly why it creates false confidence.
- Transitive, downstream dependents. Anything that depends on something that depends on the element — two, three, four hops away. A nightly batch job reads from the CRM. A data warehouse ingests that batch job's output. Six dashboards are built on the warehouse table. None of those dashboards has a direct relationship to the CRM in anyone's mental model, but every one of them breaks the day the CRM disappears.
- Affected business processes. Applications don't retire in a vacuum; they retire underneath processes that real people run. "Customer onboarding" and "complaint handling" are business processes, not applications, and they rarely show up when someone searches for the CRM's name in a system inventory. If a process realizes one of its steps through the CRM, that process is exposed, whether or not it's modelled explicitly.
- Affected views and diagrams. Every diagram the element appears in is now wrong the moment it's retired, and someone has to know which diagrams those are — not to fix the application, but to fix the documentation, so the next person doing this same exercise in eighteen months isn't misled by a landscape view that still shows a system that no longer exists.
- Boundary crossings, as a side effect of the change. This is the layer almost nobody checks and the one most likely to cause an actual incident. Retiring the CRM might mean rerouting a data flow that used to stay inside a restricted domain through a different path that now crosses into a shared or public zone — not because anyone decided to change the security posture, but because nobody traced what the replacement wiring actually implies once the old system is gone.
A retirement decision made on the strength of the first layer alone — "we checked, only two systems call it directly" — is not a complete impact analysis. It's a plausible-sounding partial one, and the gap between the two is exactly where retirements turn into incidents three weeks after the go-live date everyone signed off on.
Why this is normally a manual search
In a diagram-first tool, none of the five layers above is a query. Each one is a search, and a search is only as good as what was drawn and what the searcher happens to remember. The landscape diagram from the last portfolio review shows the CRM with three arrows coming in. The integration architect, from memory, adds a fourth — a webhook that was wired up after that diagram was last touched and never made it back into any picture. Nobody thinks to check for the nightly SQL job that reads directly from the CRM's database, because a raw database read was never something anyone thought belonged on an architecture diagram in the first place, so it was never modelled as a relationship anywhere.
The transitive layer is worse, because it requires someone to hold multiple diagrams in their head simultaneously and manually chase a chain across them — the CRM feeds a batch job, shown on one diagram maintained by a different team, which feeds a warehouse table, shown on a diagram that hasn't been opened in a year. Business process impact is worse still, because processes are frequently not modelled as first-class objects at all; they live in a separate BPMN tool, or a SharePoint site, or someone's head, disconnected from the application landscape that's supposed to realize them. And boundary crossings are the layer most likely to be skipped entirely, because checking it means re-deriving, by hand, what the network topology looks like after the change — a task nobody does unless a security review specifically forces it.
None of this is a criticism of the people doing the work. It's a description of what happens when the only representation of "what depends on what" is a set of independently maintained pictures, each accurate on the day it was drawn and silently decaying afterward. The information required to answer the retirement question completely usually does exist somewhere in the organization. It's just distributed across tools, memories, and formats that don't talk to each other, which means completeness depends entirely on how thorough and how lucky the person doing the search happens to be.
Turning it into a graph traversal
A canonical model changes the shape of this problem, because it changes what there is to query. Every application, service, database, process, and actor is a node. Every relationship — uses, serves, realizes, reads-from, is-triggered-by — is a directed edge between two nodes. Once that graph exists as the single record of dependency, rather than as an incidental byproduct of a set of diagrams, the five layers above stop being search tasks and become graph operations that run in one pass over the whole model, not just over whatever happens to be drawn.
This is what the graph analysis layer in Mooodels is built to do. The relevant operations are the standard vocabulary of graph traversal, applied to an architecture model instead of a social network or a road map:
- Incoming / outgoing relationships for any single element — the direct dependents and direct dependencies, instantly, for anything in the model.
- Upstream impact — everything that would be affected working backward from the element: who depends on it, transitively, in every direction relationships flow toward it.
- Downstream impact — the mirror case: everything the element itself depends on, which matters when the question isn't "what breaks if we remove this" but "what else are we implicitly retiring or orphaning along with it."
- Shortest path between two elements — useful for a very specific and very common question: "does the CRM have any route, direct or indirect, to the payments platform?" — which turns a vague worry into a concrete yes/no with the actual path shown.
- Reachability — can element A reach element B at all, through any chain of relationships, regardless of length. This is what answers "is there really nothing left connecting these two systems" with certainty rather than a guess.
- Cycle detection — surfaces circular dependencies, which matter enormously in a retirement scenario, because a cycle involving the element being retired usually means something is depending on it in a way nobody documented on purpose.
- Connected components — groups the model into clusters of things that relate to each other at all. An element sitting in a component by itself is a very different retirement than one embedded in a densely connected cluster of thirty other systems.
All of these run over the live model, not over a cached diagram, which means the answer reflects the relationship that was added last week just as reliably as the one that's been there for five years. Run against a model of any realistic size, they return in the time it takes to click a node — this is graph traversal over a few thousand elements, not a data warehouse scan.
Selecting the legacy CRM on the canvas and asking for its full upstream impact produces one consolidated answer covering all five layers at once:
Upstream impact — Legacy CRM (all depths)
→ 3 direct dependents
→ 11 transitive dependents (max depth 4)
→ 2 business processes realized through this element
→ 6 views reference this element
→ 1 boundary crossing introduced if rerouted through "Integration Hub"
That single query replaces the diagram search, the Slack thread, and the spreadsheet. It doesn't replace the judgment about what to do with the answer — more on that shortly — but it means the judgment starts from a complete picture instead of a partial one.
It's also worth noting what the result is attached to. Each line in that summary is a set of elements in the model, not a number in a report, so the answer is navigable: the three direct dependents can be selected on the canvas and highlighted in place, the six affected views can be opened one after another, and the boundary crossing can be traced along the specific path that introduces it. A count tells you the size of the problem. Being able to walk from the count to the elements behind it is what turns the analysis into something a retirement plan can be written from.
A worked scenario: retiring the legacy CRM
Here's how this plays out on an actual retirement, step by step, using the layers defined earlier as the checklist.
Step 1 — direct dependents
Selecting the CRM element and running incoming relationships returns three direct dependents: the Sales Portal, which calls its REST API for lead lookup; the Support Console, which queries it live during a customer call; and a Nightly Export Job, a scheduled process that was added eighteen months ago and never made it into the landscape diagram that predates it. That third one is the whole point of doing this as a query rather than a search — it was never going to show up by asking around, because the person who wired it up left the team, and it was never drawn because nobody considered a scheduled export worth putting on a picture.
Step 2 — transitive dependents
Extending the traversal outward from the Nightly Export Job surfaces a Reporting Warehouse that ingests its output, and from the warehouse, four dashboards used by regional sales managers for pipeline forecasting. None of these four dashboards has any direct relationship to the CRM — they relate to the warehouse, which relates to the export job, which relates to the CRM. A search limited to "what points directly at the CRM" would never find them. A traversal that follows the chain to whatever depth it actually goes finds all four in the same pass that found the export job.
Step 3 — business processes
The CRM element has two process realizations attached to it in the model: "Lead Qualification" and "Customer Onboarding." Both processes have steps that assume the CRM is available and populated. This is the layer that turns a technical retirement into a business conversation, because it's not "the Sales Portal will throw an error" — it's "lead qualification, as currently run, has a step that stops working," which is a sentence a process owner outside IT can actually act on.
Step 4 — affected views
The model reports six views that reference the CRM element: the executive application landscape, two integration diagrams maintained by different teams, a security zone diagram, and two views embedded in older architecture decision records. Every one of those becomes stale the day the CRM is retired unless it's updated — and because the element is referenced rather than duplicated across those views, updating it once (marking it retired, or removing it) is what actually needs to happen, not six separate manual edits across six files that may or may not all get found.
Step 5 — boundary crossings
This is the step that almost got missed. The CRM currently sits inside a Customer-Data-Restricted zone, and the Nightly Export Job runs entirely inside that same zone before landing in the warehouse — no boundary crossing today. But the retirement plan calls for the export logic to be replaced by a direct feed from the new SaaS CRM to the Reporting Warehouse, routed through a general-purpose Integration Hub that also serves several unrelated, less sensitive workflows. Running a boundary-crossing check on the proposed replacement wiring — not the current state, the proposed one — shows that the new path now crosses from Customer-Data-Restricted into a Shared integration zone that wasn't in the data's path before. Nobody decided to loosen the security boundary. It fell out of a well-intentioned technical choice about which integration platform to reuse, and it would have shipped unnoticed if the check had only covered the system being removed rather than the system replacing it.
| Layer | Found by manual search | Found by graph query |
|---|---|---|
| Direct dependents | 2 of 3 (export job missed) | 3 of 3 |
| Transitive dependents | 0 (not checked) | 5 (warehouse + 4 dashboards) |
| Business processes | 1 of 2 (recalled from memory) | 2 of 2 |
| Affected views | 2 of 6 (only recently touched ones) | 6 of 6 |
| Boundary crossings | Not checked | 1 found, on the replacement path |
The gap in that table is the entire argument for doing this as a query. Nobody involved was careless. The manual pass found most of what mattered and would have looked, on paper, like due diligence. It just wasn't complete, and the two things it missed — a scheduled job nobody remembered and a boundary crossing on the replacement design nobody thought to check — are exactly the kind of gaps that don't show up until after the go-live date, at which point they're incidents rather than findings.
The same pattern, on a shared database
The CRM example has a single clear owner and a fairly contained blast radius. A shared database is the harder version of the same question, because "shared" usually means nobody fully knows who's attached to it anymore. Running the identical upstream traversal against a shared customer database, rather than an application, tends to surface a longer and messier list: three applications with a documented connection, two more discovered through the connection string embedded in a legacy config file that got modelled as a relationship at some point, and a reporting tool that reads a materialized view derived from three of the database's tables — a dependency two layers removed from the database itself, invisible to anyone checking table grants.
The mechanics are identical to the CRM case — incoming relationships, then transitive impact, then processes, then views, then a boundary check on whatever replaces the shared database. What changes is the shape of the answer: a shared database tends to produce a wide, shallow dependent set rather than the CRM's narrow, deep one, and the connected-components check earns its keep here specifically, because it's the fastest way to see whether the database sits in one tightly coupled cluster or is quietly load-bearing for several otherwise-unrelated parts of the portfolio.
Reading a large result without drowning in it
Completeness has a failure mode of its own. Run an unbounded upstream traversal against a genuinely central element — a core banking platform, an identity provider, the customer master — and the answer can come back with two hundred elements in it, which is technically correct and practically unreadable. A list that long gets skimmed the same way an unreviewed two-hundred-line diff gets skimmed, and the one dependent that actually mattered is somewhere in the middle of it.
Three controls do most of the work of making a large result usable. Depth is the obvious one: the first hop answers "who calls this," the second and third answer "who is exposed to this," and past four or five hops in a well-connected portfolio almost everything reaches almost everything, so the traversal stops distinguishing anything worth acting on. Relationship type is the second, and usually the more valuable of the two — a traversal that follows serving, realization, and access relationships tells a different story from one that also follows association, which in most models is the relationship people reach for when they haven't decided what a connection actually means. Excluding association from an impact traversal frequently halves the result without losing a single real dependency.
The third is ordering the result by something other than discovery order. A dependent one hop away that carries a Tier-1 tag is a different conversation from a dashboard four hops out with no criticality property at all, and sorting by that combination — distance from the element, plus whatever criticality, ownership, or lifecycle properties the model already carries — puts the things that will actually shape the retirement date at the top of the list. None of that discards anything; the full set is still there, still complete, still exportable for the record. It just stops presenting a two-hundred-element answer as though every line in it carried equal weight.
What actually changes once the graph is complete
It's worth being precise about what improves here, because it isn't that the hard decisions get easier to make — it's that they get made on the right information instead of a plausible-looking subset of it. Before the retirement conversation in the worked example above, the team believed they had two dependents and a clean path. After running the traversal, they had three direct dependents, five transitive ones, two business processes, six views, and one boundary crossing on the proposed replacement design that needed a different integration route before anyone could sign off. Nothing about the difficulty of the decision changed — someone still has to decide whether four sales dashboards justify delaying the retirement by a sprint, and that's a business call about priorities, not a technical one about connectivity. What changed is that the decision is now being made with the actual dependency set in front of it, rather than the dependency set that happened to survive a week of Slack threads and diagram archaeology.
That's the realistic promise of graph analysis in a tool like Mooodels: it collapses the part of impact analysis that is genuinely mechanical — finding every relationship, at every depth, across the whole model, instantly and repeatably — so that the time an architect has available goes toward the part that was never going to be mechanical in the first place. Whether the risk is acceptable, whether the timing is right, whether a dashboard four people check every Monday outweighs an integration job nobody's looked at in a year — that's still a conversation with stakeholders, informed by a complete picture instead of guesswork about whether the picture is complete at all.
The next time someone asks "what breaks if we retire this," the honest answer stops being "give me a few days to check." It becomes: here is the complete list, here is what crosses a boundary it shouldn't, and here is the actual decision that's left for you to make.
See the model this article describes, working in a real editor.
Try the live demo