Case Study 1: The All-Arrows Diagram, Simplified

A worked before/after. The names and system are a composite—fictional but realistic—of the kind of diagram that lands in design-doc review every week.

The situation

Raj Patel was reviewing a design doc for a new "Recommendations" feature. The author wanted to show how the recommendation service fit into the existing platform, so he'd opened a drawing tool and added every component he could think of. The result was the diagram below—reproduced here in the spirit of the original, boxes and arrows intact:

flowchart LR
    A[Frontend] --> B[Backend]
    A --> C[Service]
    B --> C
    B --> D[Service2]
    C --> D
    C --> E[Cache]
    D --> E
    D --> F[DB]
    E --> F
    B --> F
    F --> G[Queue]
    G --> H[Worker]
    H --> B
    H --> D
    C --> A

Figure (described): fifteen arrows connecting eight boxes named Frontend, Backend, Service, Service2, Cache, DB, Queue, and Worker. Arrows run in every direction—several boxes point back to ones earlier in the flow—and at least four arrows cross each other. No arrow is labeled. No box says what kind of thing it is.

Raj read it three times and still couldn't answer a basic question: when a user loads the homepage, where do recommendations come from? The diagram contained the answer somewhere in its fifteen arrows, but it didn't communicate it. So he did what a confusing diagram always forces: he scheduled a call to ask the author what it meant. That call is the cost. A diagram exists to make that call unnecessary.

What was actually wrong

When Raj and the author talked, the problems sorted into the chapter's categories fast:

  • No level of abstraction. "Backend" was an application; "Cache" was a Redis instance (a technology); "Service" and "Service2" were two different microservices. Four kinds of thing, one picture, no way for the reader to tell which was which. (§32.2)
  • Meaningless names. Service, Service2, Cache, DB. The author knew which was which; nobody else could. A box's name is half its communication, and these spent nothing. (Common Mistake 4)
  • No arrow labels. Every arrow was a bare line. B → C might mean "Backend calls Service," or "depends on," or "sends data to." The reader had to guess fifteen times. (Common Mistake 2)
  • No direction. Arrows pointed left, right, and backward. H → B and C → A looped back, so the eye had no grammar to follow—it couldn't even tell where a request started. (§32.7)
  • Crossing arrows. Several crossed, reading as connections that weren't there. (§32.7)

The author's instinct had been completeness—show everything, leave nothing out. That instinct produced the exact failure the chapter warns about: a picture that's technically complete and communicatively empty.

The fix: one idea, one level

Raj asked the question that fixes most diagrams: "What's the one thing a reader of this doc needs to understand?" The answer: how a homepage request produces recommendations. Not the deploy topology, not the cache-eviction policy—just the request flow for the new feature.

That single decision deleted half the boxes as off-topic. The cache's relationship to the database, the worker's two inbound arrows—none of it served the one idea. Then they renamed what survived and labeled the arrows:

flowchart LR
    User([User]) --> Web[Web Frontend]
    Web -- "GET /home" --> API[Platform API]
    API -- "fetch recs" --> Recs[Recommendation Service]
    Recs -- "read cached recs" --> Cache[(Redis Cache)]
    Recs -- "on cache miss, query" --> Model[Model Store]
    Recs -- recommendations --> API
    API -- page + recs --> Web

Figure (described): a left-to-right request flow. A User hits the Web Frontend, which sends "GET /home" to the Platform API. The API calls the Recommendation Service to "fetch recs"; that service reads cached recommendations from a Redis Cache, and on a cache miss queries the Model Store. Recommendations flow back to the API, which returns the page plus recommendations to the frontend. What it shows: that recommendations are served from a cache first and computed only on a miss—the one performance fact a reader of this design doc needs.

Eight unlabeled boxes and fifteen tangled arrows became seven labeled boxes and six labeled arrows, all flowing one direction. The "Service2," the "Queue," and the "Worker" didn't vanish from the system—they moved to a second diagram about the offline pipeline that recomputes the model, captioned for that separate question.

The lesson

Raj added a caption to the new diagram—"Homepage recommendation request flow: served from cache, computed on miss"—and a one-line note: "The offline model-recompute pipeline is shown in Figure 2." That note is the honest move from §32.8: it tells the reader what this diagram deliberately leaves out, so the simplicity isn't a lie.

The before diagram failed not because it was wrong—every arrow described a real connection—but because it had no idea what it was trying to say. The fix was never to clean up the arrows. It was to back up, pick the one idea and the one level, and let that choice decide what stays. Renaming and labeling came second; the meaning came first—the editing hierarchy of Chapter 12, applied to a picture. The result is a diagram a new engineer understands in ten seconds, and a call that never has to be scheduled.


Back to: Chapter 32 · Case Study 2 · Key Takeaways