“I’m afraid to touch that service” is one of the most expensive sentences in software engineering. It describes a system where the dependencies are unclear, the blast radius of a change is unknown, and the safer move is paralysis. Most microservice teams have at least one service like this — often the most critical one.
Dependency mapping is the practice of making those relationships explicit, queryable, and visual. It doesn’t remove complexity, but it makes complexity navigable.
What a Dependency Map Actually Contains
A useful service dependency map answers four questions for every service in your system:
- What does this service call? (downstream dependencies)
- What calls this service? (upstream dependents)
- Who owns it? (team responsibility)
- What state is it in? (active, deprecated, migrating)
Answering these four questions for every service gives you everything you need for impact analysis (what breaks if I change X?), incident response (who do I page?), and onboarding (how does the system hold together?).
Two Approaches: Runtime Discovery vs. Explicit Declaration
There are two fundamentally different ways to build a dependency map.
Runtime discovery traces actual network traffic to infer dependencies — tools like Datadog’s Service Catalog, AWS X-Ray, or service mesh sidecars. These are accurate for dependencies that are currently active and trafficked, but miss intended-but-unused dependencies, misrepresent deprecated-but-still-called services, and require your entire observability stack to be in place.
Explicit declaration asks teams to define dependencies in a configuration file. This requires a small maintenance discipline but gives you control: you can represent services that aren’t trafficked yet, mark deprecated dependencies that should be removed, and add metadata that runtime tools can’t infer — like owning team, status, and technology stack.
For most teams, explicit declaration is the right default. It works without instrumentation, it’s queryable offline, and it produces a map that represents intent, not just observed traffic.
How to Build Your First Dependency Map in an Afternoon
- Inventory your services — List every service in production. If you don’t have a complete list, your service registry, deployment manifests, or DNS records are the most reliable sources.
- Define a YAML schema — For each service: name, team, tech stack, status, and a list of dependencies. Keep it minimal; you can always add fields later.
- Fill in the blanks — Have each team own their service definitions. Distribute the schema and give teams 30 minutes. Most of the information already exists in engineers’ heads; you’re just making it persistent.
- Visualize it — Parse the YAML into an interactive graph. Filter by team, status, or tech stack. The visualization is what makes the map useful — a YAML file alone is too hard to query mentally at scale.
- Add it to your repo and PR process — The YAML lives in source control. Dependency changes require YAML updates. Now the map is self-maintaining.
The Hover-Trace Pattern: Making Dependency Maps Actionable
A static graph of 50+ services becomes visually overwhelming fast. The pattern that makes large service maps usable: hover-tracing. When you hover over or select a node, the graph immediately highlights only the upstream and downstream dependencies of that service — dimming everything else. This transforms the map from a decoration into a tool for answering specific questions: “If I deprecate this service, what stops working?” takes two seconds to answer instead of 20 minutes of code archaeology.
Service Map implements this out of the box — YAML-defined services, interactive hover-tracing, filter-by-team or tech-stack, and shareable URLs that encode the current filter state. Self-hosted, static files, one-time purchase.
Frequently Asked Questions
How often should a dependency map be updated?
Every time a dependency changes — which means it should be part of the PR process for any service change that adds, removes, or modifies a service-to-service call. If the update happens in the same PR as the code change, the map never drifts.
What’s the difference between a service dependency map and a service mesh?
A service mesh (Istio, Linkerd) manages traffic between services at runtime. A dependency map is documentation — a queryable representation of the intended relationships between services. They serve different purposes and aren’t substitutes for each other.
