A3.7 · Tracer bullets · dive 1
End to end first
The first slice to ship is one thin thread through every layer — not one layer built fully.
Threading the system end to end exercises the seams on day one, so integration risk
is paid down early instead of accumulating to the end. On the Portal, the tracer is rung
f6.1 — the engine served as a web app (request → facade →
render). Pick a delivery strategy on the right to see how much of the stack the first shippable unit
touches.
First shippable unit · thread vs layer
One thin thread, not one full layer
A web chapter has layers: a request enters an endpoint, the endpoint calls a facade, the facade reads or writes through persistence, and a view renders the result. There are two orders in which to build them. Layer-by-layer builds each fully before the next — the whole persistence layer, then the whole facade binding, then the whole view — and leaves the seams between them to be joined at the end, where the most surprises hide. Threading builds one thin slice down through all of them at once: a tracer bullet.
The point of threading first is risk. The hardest thing to get right is rarely a single layer; it is the seams — the call from endpoint to facade, the shape the view expects back. A tracer exercises every seam on day one, so the integration risk is paid down before depth is added. The slice is thin on purpose: it carries one real path through the system and nothing more.
Integration risk over time
The cost of the two orders is not the same. Building layer-by-layer pushes integration — and the risk it carries — to the end of the chapter, where a late surprise is most expensive. Threading the tracer first pays the riskiest bill at rung one. The figure below plots the integration risk that remains after each rung under both orders, computed over a fixed model.
Slide across the ladder. Under tracer-first, most of the integration risk is gone after rung one, because the thread already proved the seams; under breadth-first, the risk stays near full until the layers are joined late. The two interactives teach different moves: the hero shows what the first unit touches, this one shows how the risk falls across the whole ladder.
Integration risk remaining · slide the rung
Thread the system end to end before deepening any one layer — the tracer pays the integration bill at rung one.
End to end first, on the Portal
On the Portal — the learning platform this course builds — the tracer is rung
f6.1 of the web chapter F6: the engine served as a web app. A request
enters the endpoint, calls the Portal facade, and renders a page. The demo
is “hit the root, see a page”; the harness is a single GET smoke. It is shipped
before durable persistence (f6.3) and before the rendered catalog
(f6.5) — the thread comes first, depth follows.
F6.1 is a real thin feature, kept and grown into the live platform; it is not a prototype. Every
later rung deepens the same slice, and every rung holds the master invariant: “The web layer
calls only the Portal facade and renders only the closed
%Portal.Error{} set. No controller, LiveView, plug, or template names
Portal.Engine, a repo, or GenServer.call.”
# phoenix.roadmap.md — the tracer rung, shipped before depth (verbatim cells). # | Rung | Ships (the slice) | Demo | # | f6.1 | the engine served as a web app | hit the root, see a page | # | f6.3 | durable catalog and enrollments | data survives a restart | # | f6.5 | the rendered catalog | browse the catalog | # f6.1 threads every layer at once — the first end-to-end unit. strategy = "thread" layers_touched = 4 # endpoint · facade · view · persistence path shipped_before = ["f6.3", "f6.5"] # persistence, then the rendered catalog kept = true # a real feature, grown — not a prototype # All of it under the master invariant: the web layer calls only the Portal facade.
Ship one thin end-to-end thread first — a tracer bullet — so every seam is exercised on day one and integration risk is paid down before depth is added.
F6.1 is the tracer — request → facade → render — shipped before persistence
(f6.3) or the rendered catalog (f6.5), kept and
grown into the live platform.
Thread first: the tracer is one thin slice through every layer, kept — not a layer built fully or a prototype to discard.
Recap — thread, then depth
The first slice to ship is one thin thread through every layer, not one layer built fully. The thread — a tracer bullet — exercises every seam on day one and pays integration risk down first. On the Portal, F6.1 is that thread: request → facade → render, shipped before persistence or the rendered catalog, kept and grown. The next dive sets the tracer beside its two near-neighbours — the walking skeleton and the prototype — to tell them apart.
Next in A3.7: A3.7.2 · Tracer vs prototype — a real thin feature kept and grown, an end-to-end structure with no feature yet, and a spike built to learn and then discarded.
References
The delivery-planning sources behind threading end to end first, and where it connects in the course.
Sources
- Hunt & Thomas — The Pragmatic Programmer — tracer bullets: a thin thread through the whole system to find the seams early.
- Humble & Farley — Continuous Delivery — integrate continuously and pay the integration bill down early, not at the end.
- Beck, K. — Extreme Programming Explained — small releases: the most valuable thin thread ships first.
Related in this course
- A3.7 · Tracer bullets and walking skeletons — the module hub.
- A3.7.2 · Tracer vs prototype — the next dive.
- A3.3 · Anatomy of a roadmap.md — the real file the tracer rung lives in.
- A1.02 · The pragmatic case — the pragmatic roots of the technique.
- F6 · The Portal on the web (Phoenix) — the real chapter whose tracer is F6.1.
- F6 · The request lifecycle — the thread F6.1 first ships, layer by layer.