Golden Paths
A recommended, supported route to production that removes toil without removing engineering judgement — and stays a path rather than becoming a cage.
The question, the obvious approach, and why it breaks
Every lesson starts where the work starts: an operational problem, a first attempt that is entirely reasonable, and the way production disagrees with it.
How do you make one supported way of building a service without forbidding every other way?
Teams need to make dozens of delivery decisions that have a right answer almost every time, and spending judgement on all of them leaves none for the decisions that are actually specific to their problem.
Pick the best stack, the best pipeline and the best deployment strategy, and standardise on them. One way to do everything is simpler for everyone.
The standard is chosen against today's services. The first service that does not fit — a batch job, a stateful store, a latency-critical path, an inherited system — has to either distort itself or go around, and going around is unsupported.
- The standard is chosen against today's services. The first service that does not fit — a batch job, a stateful store, a latency-critical path, an inherited system — has to either distort itself or go around, and going around is unsupported.
- Standardisation applied as prohibition converts every genuine exception into a negotiation with whoever owns the standard, which is a queue (Guardrails, Not Gates).
- Teams that cannot get an exception ship one anyway and describe it as temporary. Now the organisation has a standard *and* undocumented divergence, which is worse than having neither.
- A path with no exits stops receiving the information that would improve it: nobody leaves, so nobody reports what was missing.
What is actually happening
Underneath the tooling, which is the part that survives a change of tool.
- A golden path is a *default*, and the useful property of a default is that taking it requires no decision while leaving it requires only a reason — not permission.
- What the path removes is toil: the repetitive, automatable work of assembling a pipeline, wiring observability, choosing resource requests, writing the same deployment manifest again (Toil).
- What the path must not remove is judgement: whether this workload should be a service at all, what its consistency requirements are, what its failure behaviour should be, what its blast radius is. Those are the decisions the team is uniquely positioned to make.
- The difference between a path and a cage is what happens at the exit. On a path, leaving costs you the support the path provided — that is a real, self-enforcing cost. In a cage, leaving costs you an approval, which converts a technical trade-off into a political one.
- Paths are plural. Most organisations need two or three — a request-serving service, an asynchronous worker, a scheduled job — and pretending one path covers all of them is how the exceptions start.
A path has an exit; a cage does not
This is the whole lesson, and it is a single structural difference. Both shapes have a recommended way of building a service. They differ in what happens when a team has a genuine reason to do something else.
The self-enforcing version is better not because it is more permissive but because the cost of leaving is *real and immediate to the team leaving* — they take on the patching, the pipeline, the alert wiring. That cost does not need an approver to apply it, and it is proportional to how far off-path they went.
Team has a real constraint
-> path does not support it
-> exception request to platform team
-> queued behind other requests
-> approved in three weeks, or refused
-> team distorts the design to fit,
or ships an undocumented workaround
-> platform team never learns what was missingTeam has a real constraint
-> path does not support it
-> team leaves the path, no approval
-> takes on: own pipeline, own base image
patching, own alert wiring, own runbook
-> the exit is recorded automatically
-> platform team sees three teams left
for the same reason and paves itThe cage moves a technical trade-off into an approval queue, where it is decided by whoever has capacity rather than by whoever understands the workload. The path leaves the trade-off with the team and attaches its true cost to it — which both keeps most teams on the path for good reasons and tells the platform team exactly where the path is too narrow.
Toil off, judgement on
The qualifier that keeps a path healthy: it should reduce toil, not eliminate engineering judgement. Those are different categories of work, and a path that confuses them either fails to help or removes the team's ability to be responsible for its own service.
The test for any decision the path makes on a team's behalf: if this default is wrong for a service, will the team be the one paged for it? If yes, the team must be able to change it without leaving the path.
| Decision | Category | Who decides | Why |
|---|---|---|---|
| Pipeline stages and their order | Toil | The path | Same answer for nearly every service; no service-specific information improves it |
| Base image and patch cadence | Toil | The path | Fleet-wide property; per-team choices produce fleet-wide inconsistency |
| How rollout and rollback work | Toil | The path | Mechanically identical across services; getting it wrong is expensive and unoriginal |
| Metrics, logs and trace wiring | Toil | The path | Should exist before anyone thinks to ask for it (Instrumentation: From Code to Signal) |
| Resource requests and limits | Mixed | Path default, team tunes | Defaults get a service running; only the team knows its actual profile (Requests and Limits) |
| Deployment strategy for this change | Judgement | The team | Depends on blast radius and reversibility of the specific change (Blast Radius: If This Is Wrong, How Much Does It Affect?) |
| Consistency and durability requirements | Judgement | The team | A property of the problem, not of the delivery mechanism |
| What to alert on, and at what threshold | Judgement | The team, on path-provided signals | The path can supply the signal; only the owner knows what constitutes user impact (Alert on Symptoms, Not on Causes) |
| Whether this should be a service at all | Judgement | The team | The path makes services cheap, which is exactly why it must not be the reason one exists |
Reading the exits
Every departure from the path carries a reason, and the reasons sort into categories that call for different responses. Treating all of them as non-compliance loses the information; treating all of them as missing features leads to a path that tries to cover everything and covers nothing well.
| Trigger | Symptom | Cause | Response |
|---|---|---|---|
| The path has no shape for this workload | A batch job forced into a request-serving template, with a health check that means nothing | One path is being stretched across genuinely different shapes | Add a second path for the shape; do not widen the first one (Service Templates) |
| The path is slower than doing it manually | Teams scaffold with the platform then abandon it | Path optimised for coverage rather than for feedback time | Treat it as a defect and measure it (Developer Experience as an Operational Metric) |
| A default cannot be overridden | A latency-critical service leaves entirely to change one setting | Path confused an opinion with a constraint | Make the setting a parameter with a default, not a fixed value |
| An inherited system predates the path | The oldest and most critical service is off-path and untracked | Migration never funded | Track it explicitly as off-path; deliver fleet-wide fixes to it by another route rather than pretending it is covered |
| A genuine regulatory constraint | One service needs separated duties the path does not model | Legitimate; the path is not wrong | Document it as a permanent supported exception with a named owner |
| Preference, not constraint | A team leaves because it prefers different tooling | Also legitimate, and it costs them the support | Let them, record it, and check in a year whether the cost changed their mind |
How to do it properly
Most important first.
- Pave the path teams already walk. Watch what people actually build, then make the common case a default rather than designing the case you wish they had.
- Publish what the path covers and, explicitly, what it does not. An honest boundary is what makes leaving it a considered choice rather than a discovery.
- Make leaving a documented transfer of responsibility: the team keeps its own pipeline, patching, alert wiring and runbook. No approval, a clear bill.
- Keep judgement on the path. The path should not decide consistency requirements, error budgets or architecture — it should make the mechanical consequences of those decisions cheap to implement.
- Treat every exit as product feedback. Three teams leaving for the same reason is a missing feature, not three non-compliant teams.
- Version paths and migrate consumers deliberately, the way you would migrate an API's clients.
How much can this affect
Every production change has a blast radius. Stated as a scale so it is comparable between changes rather than adjectival — and paired with what actually contains it, because a wide scope with a real containment mechanism is a different situation from a wide scope with none.
A change to the default path affects every service created afterwards and every service that adopts the new version. Contained by versioning the path and letting existing consumers upgrade on their own schedule rather than being moved.
What can go wrong
- The path becomes mandatory, and the exception process becomes the platform team's largest workload.
- The path is so opinionated that teams on it cannot make ordinary engineering decisions — resource sizing, retry behaviour, deployment strategy — without leaving.
- The path is optional but unmaintained, so it is neither the fastest route nor a supported one, and adoption decays into nostalgia.
- Off-path services inherit none of the fleet-wide fixes, and nobody tracks that they are off-path at all.
- One path is stretched to cover shapes it was not designed for, and it becomes the worst option for everybody.
- "A golden path means one way to do things." It means one *default* way, which is a different claim: defaults are about where the burden of decision falls, not about what is permitted.
- "Removing decisions is the goal." Removing *repeated mechanical* decisions is the goal. A path that also removes the design decisions leaves teams accountable for outcomes they no longer control.
- "If teams keep leaving the path, they need to be brought into line." Teams leaving is the highest-quality feedback the platform gets. Suppressing it does not fix the path; it hides the reason.
- "Off-path means unsupported means unimportant." The off-path services are frequently the oldest and most business-critical ones.
Operating it
Evidence is the signal, not the intention. Rollback is sometimes 'you cannot, and that is the point'.
- Most new services take the path without anyone asking them to.
- You can list the services that are off-path, and for each one, the reason.
- A team that left the path did so without filing anything, and knows exactly which responsibilities it took on.
- Recent path improvements can be traced to specific exits.
- A team can return to the path. If rejoining requires a rewrite, the path is not a default — it is a platform lock-in with a friendlier name.
- A path version that turns out to be worse can be un-defaulted for new services immediately, while existing consumers migrate on their own schedule.
- Automate everything the path does mechanically: scaffolding, pipeline, wiring, defaults, propagation of improvements.
- Do not automate the enforcement of path membership. An automated block on leaving is the definition of a cage, and it produces divergence you cannot see rather than divergence you can.
- Do automate *detection* of off-path services — that is not enforcement, it is knowing your fleet.
- Defaults chosen for the common case are wrong for the uncommon one, and the uncommon one is often the most important service you have.
- Supporting exits costs the platform team real work — an off-path service still needs the fleet-wide security fix, delivered a harder way.
- Multiple paths multiply maintenance; each one is a product with its own consumers and its own upgrade obligation.
Where this applies
This domain is unusually tool- and organisation-dependent. These labels say what each claim is specific to, and what a different platform, provider or organisation does instead.
- ORG-SPECIFICWhether an exit requires approval is a policy choice, and in regulated environments some exits genuinely cannot be self-served — a change to how audit evidence is produced, for example. Where that is true, say so explicitly and keep the list of genuinely-gated exits short, rather than gating everything by default.
- SCALE-SPECIFICWith one or two teams the path is whatever the last service did, and formalising it adds ceremony to a decision two people can make in a conversation. It becomes worth naming at the point where someone joins who was not in that conversation.
Where the depth lives
This domain teaches delivery and operation, and hands the mechanism off to the domain that owns it.
- — Testing & Reliability Engineering — how much of the confidence a path provides comes from the checks it runs rather than from the defaults it sets.