Platform Engineering
Building reusable internal products that make safe delivery the easy path for the teams that ship on them.
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.
When does building an internal platform make delivery safer, and when does it just add a team between developers and production?
Every team solves the same delivery problems independently — pipeline, deployment, secrets, observability, infrastructure — each slightly differently. When one of those solutions turns out to be wrong, there is no single place to fix it.
Write the setup down. A good wiki page describing how to configure CI, deploy and add monitoring lets each team do it correctly for themselves, without a new team owning anything.
Documentation describes a configuration; it does not produce one. The first team follows it, the second copies the first team's repository, and the third copies the second — including whatever was wrong in it.
- Documentation describes a configuration; it does not produce one. The first team follows it, the second copies the first team's repository, and the third copies the second — including whatever was wrong in it.
- The page goes stale silently. Nothing fails when the instructions no longer match the tooling; the next person just spends a day discovering it.
- When a fix is needed — a base image with a fixed CVE, a health check that was wrong, a deployment step that drops connections — there is no mechanism to apply it. There are eleven repositories and eleven owners, and the fix reaches whichever of them read the message.
- Nobody owns the aggregate. Each team owns its own pipeline, so the pipeline that eight teams depend on being similar is owned by nobody (Shared Ownership).
What is actually happening
Underneath the tooling, which is the part that survives a change of tool.
- A platform is a product whose users are engineers. That is not a slogan: it means it has an interface, consumers who chose it, a support burden, a compatibility obligation and a roadmap that someone must own.
- The leverage is entirely in the second derivative. A fix applied to a platform reaches every consuming service; a fix applied to one team's pipeline reaches one team. That is the only reason to accept the extra layer.
- The interface is the load-bearing decision. What a team asks for ("a service", "a database", "a queue") is separate from what actually happens (a repository, a pipeline, a role, a secret store entry, an alert route). If the interface is stable, the implementation can be changed underneath it — which is exactly the fix-once property you built the platform for.
- Adoption is voluntary in practice regardless of what policy says. If the platform is slower or less capable than what a team can build itself, teams route around it and you now maintain two systems instead of one.
A product, whose users can leave
The distinction that decides whether a platform helps is not technical. It is whether teams *choose* it because it is the fastest way to do the thing, or *use* it because they are not permitted to do anything else. The two produce identical architecture diagrams and opposite outcomes.
The reason is feedback. A platform teams can leave gets honest signal when it is bad: adoption stalls, and the platform team finds out. A platform teams cannot leave gets no signal at all until it shows up as delivery being slow everywhere, which is attributed to something else.
Team needs a service
-> must use platform
-> platform does not support their case
-> exception request
-> waits behind other requests
-> team ships a "temporary" bespoke pipeline
-> it is still there two years laterTeam needs a service
-> platform path takes an afternoon
-> team takes it, because it is faster
-> unsupported case appears
-> team goes off-path, keeps the responsibilities
-> platform team sees the exit and either
supports the case or documents why notIn the first shape the exception process is the platform team's queue, so every unsupported case becomes their capacity problem and the team's delay. In the second, going off-path costs the team the support the platform provided — a real cost that does not require anyone's approval, and one that shows the platform team exactly which cases are missing.
What is actually being centralised
A platform is not one decision. It is a set of separate concerns, each of which can be centralised or left with teams independently — and each of which costs something specific when centralised.
Reading them as a list rather than as a package is what lets a small organisation take the two that pay for themselves immediately and skip the rest.
| Concern | Left with each team | Centralised | What centralising costs |
|---|---|---|---|
| Build and CI config | Copied between repos; drifts | One pipeline definition, one place to fix | A team with an unusual build fights the shared one |
| Base images | Each team patches, or does not | Patch once, rebuild everything (The Delivery Chain as Attack Surface) | A base image change is now a fleet-wide change |
| Deploy mechanics | Each team learns rollout the hard way | Rollout, health gating and rollback are the same everywhere | The team no longer sees why the deploy is safe |
| Infrastructure provisioning | Each team writes its own IaC | Reviewed modules with sane defaults (Modules: Reuse Without Hiding) | Defaults that suit most teams suit some team badly |
| Secrets | Ad hoc; often ends up in CI variables | One issuance and rotation path (Rotation That Applications Survive) | A central store is a central failure domain |
| Observability wiring | Present when someone remembered | Metrics, logs and traces on by default (Instrumentation: From Code to Signal) | Instrumentation nobody chose is instrumentation nobody reads |
| On-call and ownership | Team owns its service | Ownership *records* centralised; the duty stays with the team | Centralising the duty itself rebuilds the wall |
Deciding whether to build one at all
A platform is a bet that duplication across teams will cost more over time than an extra layer and the people to maintain it. Below a certain size that bet is clearly bad, and the honest answer is that a shared repository of pipeline configuration plus one person who fixes it does most of the job.
The signal that it has flipped is not team count on its own. It is that changes which should be one change have started arriving as one change per team, and that nobody can say with confidence what every service is currently doing.
Who builds and maintains the path from repository to running service?
when One to three teams, or services with genuinely unrelated shapes.
cost Duplication; fixes reach whoever hears about them; no aggregate view of what is deployed anywhere.
when A few teams with similar services. Pipeline templates and IaC modules live in one repository that everyone contributes to.
cost Ownership is diffuse — it works while someone cares and decays quietly when they move on.
when Enough teams that the same change has to be made in many places, and enough consumers to justify people whose product is delivery.
cost Headcount not shipping features; an extra layer to debug; a new possible bottleneck to manage against.
when A managed platform covers your shape and you would rather spend the people elsewhere (No Cargo-Cult Infrastructure).
cost Vendor constraints become your architecture constraints, and leaving is a migration rather than a decision.
How to do it properly
Most important first.
- Start from the path teams walk most often and hate most, not from the most interesting piece of infrastructure. Usually that is "get a new service into production" (The Internal Developer Platform).
- Make the paved path the *fastest* path. Adoption driven by speed survives; adoption driven by mandate produces compliance-shaped workarounds (Golden Paths).
- Version the platform interface and deprecate on a published schedule, the way you would treat an external API. Consumers cannot absorb surprise breaking changes across eight teams at once.
- Prefer guardrails that make invalid states impossible over approvals that make valid ones slow (Guardrails, Not Gates).
- Measure the experience of using it — time to first deploy, feedback time, friction — and treat a bad number as a defect in your product (Developer Experience as an Operational Metric).
- Keep the exits open. A team with a genuine reason to leave the path should be able to, and should keep the responsibilities the platform was carrying for it.
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 platform change reaches every consuming service, so nothing contains it by default. What contains it is applying rollout discipline to the platform itself — versioned interfaces, a canary set of consumers, and the previous version left serving.
What can go wrong
- The platform team becomes an approval queue, which is the wall from What DevOps Actually Means rebuilt with better branding.
- The platform is built from what platform engineers find interesting rather than from what consuming teams repeat, and adoption stalls at the teams that were told to use it.
- An abstraction hides a failure mode the consuming team still gets paged for — the platform owns the mechanism, the team owns the outage.
- The platform accumulates consumers and loses its owner, becoming critical infrastructure that nobody is funded to maintain.
- The platform cannot be left, so every product decision it makes becomes mandatory for everyone downstream.
- "The platform team is the operations team renamed." The difference is the deliverable: an operations team runs things on behalf of others, a platform team ships capability others run themselves. If work is queueing on the platform team, the rename is all that happened.
- "With a platform, teams no longer need to understand production." They still get paged. A platform can remove the work of assembling a deployment; it cannot remove the responsibility for what the deployment does.
- "Adoption should be mandated so we get the consolidation benefit." Mandated adoption gets you the reporting line, not the consolidation — teams comply at the interface and diverge underneath.
Operating it
Evidence is the signal, not the intention. Rollback is sometimes 'you cannot, and that is the point'.
- A new service reaches production through the standard path in about a day, done by the team that owns it and without a platform engineer in the room.
- A change to the base image or the deploy step reaches every consuming service without one ticket per team.
- Teams that were not told to adopt it adopt it anyway.
- When a platform-owned component causes an incident, it is clear before the incident who is paged for it.
- A platform is infrastructure that many teams depend on, so "roll back the platform" means every consumer changes at once. Treat platform releases with the same rollout discipline as a service: version, canary against a subset of consumers, keep the previous version serving (Canary: One Percent, Then Five, Then Watch).
- Reversing the *decision* to have a platform is much slower than reversing a release. That is an argument for keeping the escape hatch working, so that leaving is a per-team decision rather than an organisational project.
- Automate provisioning, wiring and the propagation of platform changes to consumers — these are the repeatable steps whose whole value is that they are identical every time.
- Do not automate the decision to adopt. A mandate enforced in tooling produces teams that satisfy the tooling and solve their real problem somewhere you cannot see.
- Keep support human. Most of what a platform team learns about its product arrives through someone being stuck.
- Below a certain number of delivery teams a platform costs more than the duplication it removes, and the same engineers could have simply fixed the one pipeline that exists.
- Every abstraction adds a layer to debug through. When something breaks, the consuming team now has two systems to reason about instead of one.
- Platform velocity becomes the organisation's velocity ceiling. Anything the platform does not support is either slow or off-path.
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.
- SCALE-SPECIFICThe overhead flips somewhere around five to ten delivery teams, or the point where more than one person is maintaining a copy of the same pipeline. Below that, a shared repository of build configuration and one person who fixes it is cheaper and reaches the same services. Above roughly ten, the duplication cost is paid every time anything needs changing everywhere.
- ORG-SPECIFICWhether a platform is a team, a rotating responsibility or a vendor product is an organisational choice. A regulated environment often gets the platform first, because centralised evidence of controls is easier to produce than per-team evidence — that is a compliance driver, not a delivery one, and it produces a different product.
Where the depth lives
This domain teaches delivery and operation, and hands the mechanism off to the domain that owns it.
- — System Design — how the shape of the services being delivered decides how much a shared path can actually cover.