You change one file. Three features break. Your PM is furious, your on-call engineer is pulling an all-nighter, and you're staring at a rollback wondering what the fuck just happened.
The problem isn't that you made a mistake. The problem is that nobody — not you, not your IDE, not your CI system — knew that validatePaymentMethod() was secretly load-bearing code for checkout, subscriptions, AND the admin refund flow.
Most impact analysis is theater. Your IDE shows you "3 references" because it can grep for function calls. Your test coverage says 80% because someone wrote tests that don't actually exercise the critical paths. Static analysis tools draw pretty graphs that miss half the dependencies because they can't see through your event bus or that weird reflection hack in the ORM.
We built Glue's blast radius system because we got tired of playing Russian roulette with deploys. Here's how it actually works.
Nobody tests the error paths that actually happen in prod
I've seen files with 100% coverage cause three-hour outages.
Lie #3: Humans remember the dependency graph.
They don't. The engineer who built the payment system left eight months ago. The refactor that "simplified" checkout actually made it depend on six new services. That temporary workaround from Q2 is now load-bearing infrastructure.
Your brain has maybe 7±2 working memory slots. Your codebase has ten thousand files and a million dependencies. The math doesn't work.
What Actually Predicts Blast Radius
We needed something better. Here's what we built.
Layer 1: Multi-Source Dependency Graph
Static analysis is the foundation, not the whole building. We parse your entire codebase to build a graph of:
Direct imports and function calls (the obvious stuff)
Type dependencies (changing an interface breaks everything that implements it)
Symbol references (that enum value, that constant, that type guard)
But then we add the invisible edges:
Runtime traces. We analyze your application logs, distributed traces, and API call patterns to discover dynamic dependencies. When POST /checkout consistently calls validateInventory() even though there's no static import, that's a real dependency.
Database schema relationships. Foreign keys, triggers, views, stored procedures. If your ORM change drops a column that a trigger reads, you need to know before deploy.
Event-driven coupling. We parse your event bus configuration, message queue bindings, and webhook registrations. That innocent model change might trigger fifteen event handlers you forgot existed.
Feature flag dependencies. Code behind a flag still affects blast radius. We track which flags gate which code paths so you can model "what breaks when we enable this?"
The result is a graph that actually represents how your system behaves, not just how it's written.
Layer 2: Feature Boundary Detection
Dependencies alone don't tell you what breaks. You need to map code to features.
We use LLM agents to analyze your codebase and discover feature boundaries automatically. The agents:
Identify API routes and their purposes
Trace backward through the call graph to find all code that supports each route
Cluster related routes into features (checkout vs subscriptions vs admin)
Map database tables to features based on access patterns
This gives us a feature topology. Now when you change validatePaymentMethod(), we can say: "This file is used by 3 features: Checkout (critical path), Subscriptions (admin flow), Refunds (edge case)."
The key insight: feature boundaries are probabilistic, not deterministic. A file might be 80% checkout, 15% subscriptions, 5% admin. We model this with confidence scores derived from:
Call frequency (how often does this code path execute?)
Historical coupling (files changed together in past commits)
Semantic similarity (LLM embeddings of purpose and context)
Now we combine the graphs. For any file change, we:
Walk the dependency graph outward from the changed file, collecting all reachable code. This gives us the potential blast radius.
Filter by feature boundaries to determine affected features. We weight edges by coupling strength — a weak dependency to an admin feature doesn't warrant the same alarm as a critical path dependency to checkout.
Apply historical signal. We analyze your git history: files that co-change frequently have hidden coupling that static analysis misses. If touching payment.ts has historically required changing invoices.ts within 3 commits, that's signal.
Score by code health metrics. Glue tracks churn, complexity, ownership, and technical debt per file. High-churn files in the blast radius are higher risk. Orphaned files with no clear owner are higher risk. Complex files with cyclomatic complexity >15 are higher risk.
The output: "Changing this file affects 3 features with 85% confidence. Checkout is high risk (complexity 23, churn 18, no owner). Subscriptions is medium risk. Refunds is low risk (only hit on errors, good test coverage)."
The Technical Architecture
Here's how we actually built this.
Indexing pipeline: We run a distributed indexing job that:
Parses all source files with language-specific AST parsers (TypeScript, Python, Go, etc.)
Builds symbol tables and cross-references
Extracts schema from ORMs, migrations, and database dumps
Ingests runtime traces from your observability platform (we support OpenTelemetry, Datadog, and custom formats)
Stores everything in a graph database (we use PostgreSQL with recursive CTEs because we're not fucking around with eventual consistency)
Agent swarm: We deploy specialized LLM agents that:
Read code in chunks (we use Claude with 200k context windows)
Identify features by analyzing route handlers, service boundaries, and database access
Generate embeddings for semantic similarity
Validate their own work through ensemble agreement (multiple agents vote)
Query engine: When you ask "what does this change affect?", we:
Run graph traversal queries (optimized with materialized paths and bloom filters)
Join with git history analysis (pre-computed co-change matrices)
Score with code health metrics (indexed by file, updated on push)
Return ranked results in <500ms (p99)
Incremental updates: We don't reindex the world on every commit. We:
Track file changes via git webhooks
Invalidate affected subgraphs only
Recompute feature boundaries when cluster centroids shift
Update incrementally (usually <10s for typical PRs)
What We Learned Building This
LLMs hallucinate, but ensemble voting catches it. A single agent might confidently assert that logger.ts is part of the checkout feature. Three agents voting reduce error rate from 23% to 4%.
Static types help more than you'd expect. TypeScript codebases give us 40% more accurate dependency graphs than JavaScript because we can resolve imports without executing code.
Developers lie in comments, commits tell truth. We tried using docstrings and README files to identify features. Git history (files changed together) was 3x more accurate.
Blast radius is fractal. The deeper you look, the more dependencies you find. We cap traversal at depth 6 because beyond that, everything depends on everything and the signal disappears.
Probabilistic is better than binary. Early versions gave yes/no answers ("does this affect checkout?"). Confidence scores are way more useful because developers can make risk-based decisions.
How This Actually Helps
You're reviewing a PR that changes database migrations. Glue shows you: "This affects 2 features: User Management (medium risk), Analytics Dashboard (low risk, read-only dependency)."
You see medium risk on User Management. You click through. Glue shows you the files in that feature with high churn and no clear owner. You tag the right people for review. You add tests for the specific code paths affected. You deploy during low traffic.
The PR still lands same day. But instead of "ship and pray," you shipped with informed confidence.
That's the point. Not to prevent all changes (that's stagnation). To predict consequences so you can prepare.
The Gaps We're Still Filling
This system isn't perfect. Here's what we're working on:
Cross-service dependencies. We handle microservices within one repo well. Multi-repo dependencies require explicit integration config (we support API contracts and OpenAPI specs, but adoption is spotty).
Mobile client impact. Backend changes break mobile apps, but mobile release cycles are slow. We're building client version dependency tracking so you can model "which app versions break if we deprecate this endpoint?"
Performance impact prediction. We know what breaks, not how fast it runs after changes. Adding query latency modeling to predict performance regressions.
Human expertise capture. Senior engineers know things that aren't in code or git history. We're experimenting with annotation tools to capture "I changed X and Y broke, even though there's no visible dependency."
Why This Matters More Now
Codebases are getting bigger. Teams are getting distributed. Knowledge is spreading thinner. The engineer who remembers why that weird validation exists is on PTO when the incident happens.
You can't rely on human memory anymore. You need systems that know your codebase better than anyone person does.
That's what we built. A blast radius oracle that actually works.
You can keep playing Russian roulette with deploys, or you can ask the oracle first. Your choice.