Case Study · 01

Redesigning the
Service Dependency Graph.

Helping engineers find their way through hundreds of API contract dependencies without losing their place.

Timeline
1 week
Team
Solo Designer
Fullstack Engineer
Role
Product Designer
Domain
Enterprise B2B · developer tools · API contract observability
— AI summary

The condensed version.

Problem: Specmatic Insights' Service Dependency Graph shows how up to 5,000 services connect through API contracts, with only 12–24 visible on screen at once — but the existing graph broke down at that scale. Controls competed for space with the graph itself, navigation aids were either missing or permanently on screen regardless of need, and there was no fast way to find a specific service or understand where you were relative to the rest of the system. Solution: The reframe was from "show every control, all the time" to "show the graph, and let controls earn their place on screen" — search, filters, a directional pad, and a minimap all still exist, but now appear based on what the user is actually doing rather than living in a fixed toolbar. Impact: This design was handed off for usability and QA testing, so what follows are concrete before→after design changes rather than tested metrics — toolbar actions cut from 8+ competing controls to the 7 that directly support finding, understanding, or navigating a service, and the graph promoted from a bounded dashboard card to a fullscreen-capable primary workspace.

The throughline: the real work was deciding which controls hadn't earned their place on screen, not making the existing ones prettier. Conditional UI — navigation aids that appear only once the graph's complexity justifies them — did more for the interface than any single new feature would have.

01 Quick Summary

Problem, solution, and the impact being tested.

01

Problem

The graph in Specmatic Insights had to handle 100 to 5000 services, but the old design could show up to 24 at a time before it became unreadable. It maps how software's many small services rely on each other: in an online shop, checkout needs payment, and payment needs a fraud check. Each node is a service and each arrow connects it to one that uses it. As the graph grew, engineers couldn't find a service, follow the arrows, or keep their place, and so couldn't answer "if I change this, what could break?"

02

Solution

From "show every control, all the time" to "show the graph, and let each control earn its place." After team feedback on v1, I went further: scope the graph to the person looking at it, by team, with filters and a hover card that answers the questions engineers actually ask.

03

Impact

Design changes, handed off for testing, no measured results yet:

  1. 01Corner icons with no search and no service count → header with search and a service count, plus one bottom bar for zoom, fit, reset and fullscreen.
  2. 02Directional pad and minimap → conditional: pad only when zoomed in, minimap only above 150% zoom and 50 nodes.
  3. 03Graph card in a long dashboard → fullscreen-capable workspace with the same bottom navigation and a clear exit.
  4. 04Bare node name → hover card with Name, Exposes, Used by, Depends on, and colour-coded upstream and downstream edges.
  5. 05One wall of 100 nodes → two proposed entry flows to test: team-scoped from login or open with Team and Services filters.
02 Preview

The redesign, live.

Open the interactive prototype
An interactive prototype of the redesigned graph — the toolbar, contextual navigation, and fullscreen mode described below, actually working. Opens in Figma, in a new tab.
03 Context

The scale wasn't hypothetical.

  1. Product. Specmatic turns API specs into executable contracts. Insights is its visibility layer, and the graph shows who provides what and who consumes it.
  2. The graph. Built from CI/CD reports, so it shows logical contract relationships, not runtime traffic. Arrows run from provider to consumer.
  3. Users. Developers, architects, platform and QA teams, governance, SREs, managers and new engineers, all trying to find a service, judge a change's impact or get oriented.
  4. Why a redesign. The old limit of 24 readable nodes against a target of 100 to 5000 was the main reason. A visual refresh would not move it.
  1. What the product does. Specmatic helps engineering teams work with API contracts and verify that services actually communicate the way those contracts say they will. Insights is the visibility layer on top of that — and the Service Dependency Graph is the part of Insights that shows which services depend on which, a logical contract-relationship graph, not a runtime infrastructure map.
  2. Who relies on it. Not one type of user — backend/API developers, contract owners, platform engineers, architects, EMs, QA/test teams, DevEx/governance teams, SREs, and engineers new to a codebase all use this graph, each with a different job: find a service, assess blast radius, scope regression tests, understand ownership, or just get oriented in an unfamiliar system.
  3. Why the complexity is real, not invented. The intended scale is 100–5000 services with only ~12–24 visible at a time. That's not a hypothetical edge case — it's the baseline the graph has to work at from day one, which means "more services" reliably means "more relationships, more visual noise, harder navigation."
  4. Why this needed a redesign, not a visual refresh. The existing graph's problems weren't cosmetic. Nodes could exist with no visible relationships and no explanation why. The canvas didn't use its own space efficiently. Controls were permanently present regardless of whether the current view needed them. These are structural, information-hierarchy problems — repainting the same toolbar wouldn't have fixed any of them.
04 Process

How the week ran.

Audit Benchmark First design Team feedback Revised design

Benchmark: Cortex, Backstage, OpsLevel, Port, Datadog and Dynatrace, read for navigation and scale handling, not visual style.

Most of the tools handle a big graph by making you cut it down before you can read it: you pick a filter, set how many links to follow, or choose an area. That made me ask a different question: why start from the whole system at all?

Benchmark of six tools: Cortex, Backstage, OpsLevel, Port, Datadog and Dynatrace, with what stood out, what I took and what I left out
05 Simplifying the Toolbar

Controls should earn their place.

  • Before: No search and no service count. Only green circular icons in the corners: four directional arrows at the bottom left, zoom in, zoom out and fit at the bottom right, always on screen. Finding a service meant panning and reading node names.
  • Reframe: Break the task into find, understand, move around, stay oriented, recover, then ask of every control: which step does this serve?
  • Result: Header with search and the service count ("Showing 100 of 100 Services"). Corner icons became one bottom bar: zoom out, zoom in, fit, reset and a fullscreen toggle. Fit shows overall structure; reset returns to default. Search narrowed by about 20% during iteration so it is the fast path without dominating.
Image: Live graph controls vs. v1 header and bottom bar

What the legacy approach made users do

The original graph toolbar carried a View dropdown, Previous and Next buttons, and an Export action — all competing for the same visual space as the graph itself, alongside search, filters, and the graph controls that actually mattered for navigation. A user opening the graph to answer "what does this service depend on?" had to visually filter out four controls that had nothing to do with that question before they could even start.

The obvious fix, considered and rejected

The easy move here would have been a visual refresh — restyle the same toolbar, tighten the spacing, call it done. That was set aside quickly: the problem wasn't that the controls looked cluttered, it was that they were cluttered with the wrong things. Restyling doesn't fix a control competing for space it hasn't earned.

The reframe

The real question wasn't "how do we fit these controls in more neatly" — it was "does this control directly help the user understand or navigate the dependency graph?" Anything that didn't clear that bar came out entirely, rather than being made smaller.

The result

View dropdown, Previous, Next, and Export were removed outright. What remained — total service count, search, zoom, fit, reset, filters, and the graph itself — earned its place because each one maps directly to a step in the actual user task (find → understand → navigate → orient → focus). Search was kept but narrowed by roughly 20%, sized as a fast path to a specific service rather than a dominant toolbar element. Filters were rebuilt as compact, canvas-anchored elements instead of a toolbar row, so the graph — not the chrome around it — stays the dominant visual element.

Screenshot: legacy toolbar vs. simplified toolbar
The legacy toolbar (View dropdown, Prev/Next, Export competing with search and filters) compared against the simplified version — 7 controls, each mapped to a step in the actual task.

Removing a control outright is a stronger move than restyling it. The question isn't how to fit everything in more neatly — it's what hasn't earned its place at all.

06 Contextual Navigation

When does a nav aid earn its space?

  • Before: Directional arrows always on screen at any zoom; no overview at any zoom.
  • Rejected: A permanent minimap. On small graphs it is a second layer nobody needs, and it takes canvas.
  • Reframe: Not "should it exist?" but "when does an aid justify its space?"
  • Result: The four-key pad appears only when zoomed in, above the bottom bar with Down under Up. The minimap appears only above 150% zoom and 50 nodes. The bottom bar stays put, so only the pad and minimap come and go. Small graphs stay clean.
Image: Board 02, open default with pad and minimap

What the legacy approach made users do

In the current build, navigation aids don't yet track the user's actual context. A directional control sits on screen at all times regardless of zoom level, and there's no minimap at any zoom level — so on a small graph the interface still carries navigation weight it doesn't need, while on a large, deeply-zoomed graph, there's nothing to answer "where am I relative to the rest of the system?"

The obvious fix, considered and rejected

The default pattern most graph tools reach for is a permanent minimap, always in the corner. That was ruled out — for a graph that's frequently small or simple, a permanent minimap is a second navigation layer the user doesn't need yet, and it takes up canvas space that could go to the graph itself.

The reframe

The guiding question became "when does a navigation aid actually justify the screen space it takes?" — not "should this feature exist," but "when should it appear." That produced two explicit, testable conditions instead of an always-on/never-on binary: the 4-key directional pad appears only once the user is sufficiently zoomed in, positioned just above the bottom toolbar with Down directly under Up so it reads as a deliberate controller, not a scattered set of arrows. The minimap appears only when zoom exceeds 150% and the graph has more than 50 nodes — the two conditions under which a user is genuinely likely to lose spatial context.

The result

Both aids go from either permanently present or entirely absent to conditionally available exactly when the graph's complexity justifies them — small and simple graphs stay clean, while large, zoomed-in graphs get the orientation support they need without that support existing as visual noise the rest of the time.

Screenshot: directional pad + minimap appearing at threshold
The directional pad and minimap, appearing once zoom and node-count cross their respective thresholds — orientation support exactly when the graph's complexity justifies it.

Conditional UI needs an explicit, testable threshold — not a vague "show it when it's needed." A fuzzy rule is unbuildable and unreviewable; zoom >150% and >50 nodes is neither.

07 Fullscreen as an Exploration Mode

An exploration mode, not a magnification setting.

  • Before: The graph sat in a small card on a long dashboard page, so a graph of many services got only a small window.
  • Rejected: Just make the card bigger. A bigger card still has no controls built for exploring and no clear way back to the dashboard.
  • Reframe: Fullscreen should be a way of exploring, not just a bigger view.
  • Result: A fullscreen toggle opens the graph across the whole screen with the same bottom bar (zoom, fit, reset) and an exit button. Closing it takes you back to the dashboard.
Image: Board 01, graph in the live dashboard

What the legacy approach made users do

The graph was bound by the surrounding webpage. Any real exploration — following a long dependency chain, comparing spread-out clusters — meant working inside a canvas that was smaller than the problem it was trying to represent, with no way to reclaim more space.

The obvious fix, considered and rejected

The straightforward version of "give it more room" is simply making the graph bigger — expand the card, shrink the surrounding page. That alone wasn't enough: making the canvas bigger without carrying navigation controls (fit, reset, zoom) and a clear exit path into that bigger view just relocates the original problem into a larger box.

The reframe

The distinction that mattered was fullscreen as an exploration mode, not a magnification setting. Going fullscreen needed to preserve every navigation aid the user relies on in the normal view — bottom navigation, fit, reset — and needed an unambiguous way back out, rather than trapping the user in an enlarged canvas with no clear exit.

The result

The graph now supports Normal webpage → Graph section → Fullscreen graph as a deliberate escalation path. The Insights dashboard context stays intact until the user chooses to leave it, and fullscreen carries the same bottom navigation and recovery controls (fit/reset) as the standard view, with an explicit way to exit back to the dashboard.

Screenshot: graph section → fullscreen transition
The escalation path from dashboard card to fullscreen — every navigation control carried through, with an explicit way back out.

More screen space only helps if the controls and the exit path travel with it. A bigger canvas that strands the user is the same problem in a larger box.

08 Scoping to the Person

Start from the person, not the system.

Team feedback on v1: show upstream and downstream clearly, colour-code dependencies, add a team filter, and give every node Name, Exposes, Used by, Depends on.

  • Before: v1 helped you cope once lost. It did nothing to stop you getting lost in 100 services.
  • Rejected: Blocking the graph until a filter is set, as most benchmarked tools do (Cortex requires one above 500 nodes). It gates the graph and fails for a new engineer who does not know what to filter by.
  • Reframe: If login already brings team data, why start from the whole system? Start from the person.
  • Result: Two flows, both requiring login, proposed for side-by-side testing:
    • Flow A, scoped default: the graph opens as your team's services, with a "Show all services" button. Search reaches every service.
    • Flow B, open default: the full graph with Team and Services filters. Selecting two services tags a shared downstream "Used by both".
  • Hover and click: hover opens the four-field card; edges turn blue for what it depends on and orange for what uses it; the rest steps back. Click opens the existing service detail, so no second place for the same information.
Images: Board 03 hover; Boards 04 and 05 filters; Board 06 scoped default
09 Team Dynamics

A side panel the product didn't need.

My v1 had a side panel with team, dependency counts and a health status per service. The team's feedback pointed out that the panel was not a functionality of the product. The product has no health status on services, and clicking a service already opens a detail view. I took it out, moved the four facts onto hover, and rebuilt around what the product actually does.

10 Conclusion

Craft lessons, and one deeper one.

Craft lessons

  • Removing a control beats restyling it. Ask "does this help the task?", not "how do I fit this in?"
  • Conditional UI needs a testable rule: "above 150% zoom and 50 nodes" can be built and reviewed; "when it's needed" cannot.
  • Not getting lost beats tools for being lost. The scoped default was the biggest change from v1 to v2.

One deeper lesson. A design only holds if it is checked against what the product really does. My side panel looked right but assumed data that did not exist. Now I check ideas against the real product and data before they reach the team.

What's next. The design is with engineering for testing. Open questions: which flow gets people to a service faster, and how login team data maps to services.