Four engineers. Nine clusters. A roadmap with eleven items on it, none of which had moved in a quarter.
That was the situation when I was asked to look at why a platform team felt slow. Nobody on that team was slow. They were good. They were also spending most of every week answering questions.
The week nobody planned
I asked them to keep a tally for five working days. Not a time sheet, just a mark every time someone outside the team asked for something. The tally came back at 61.
Sorted by kind, it looked like this:
- 19 requests for access to something
- 14 questions of the form "how do I get an ingress for X"
- 11 requests to bump a resource limit
- 8 "is this the right way to do Y"
- 6 incidents or suspected incidents
- 3 that were actual platform work
Three. Out of sixty-one. And the eleven roadmap items sat where they were, because the roadmap is what you do with the time left over, and there was none.
The part that gets misdiagnosed
The usual reading of that tally is "we need more people" or "we need a self-service portal". Both readings skip a step.
Look at the two biggest buckets again. Access requests and ingress questions are not hard. They are not even interesting. They get asked because nobody can look up the answer. The answer lives in the head of whichever platform engineer answered it last time, and it varies slightly depending on who that was.
A platform team in that state has an API. It is just undocumented, unversioned, and implemented in a chat channel by whoever is awake.
The question
So: what separates a platform team from a platform?
Not the technology. Every one of those nine clusters was competently built. Flux was wired up, Prometheus was scraping, the network policies were real. The machinery was fine.
What was missing was a statement of what the machinery promises.
Write the promises down
Here is the exercise I have now run three times, and it takes an afternoon.
List every thing a team needs from the platform in order to run a service. Not what the platform can do. What a service actually needs, in the order it needs it. For most organisations the list is short and looks roughly like this:
- A place to run (namespace, quota, who can deploy)
- A way in (ingress, TLS, DNS)
- A way to hold a secret
- A way to see what it is doing (logs, metrics, a dashboard)
- A way to undo a deploy
- A way to get help when it breaks
Six items. Now, for each one, write three things: how a team gets it, how long that takes, and who to talk to when it does not work.
That document is the interface. It does not have to be a portal. The first version we wrote was a single Markdown file in the platform repo, 340 lines, with kubectl commands and a link to the pull request template for namespace requests.
The effect was immediate and slightly deflating for everyone involved: the tally dropped from 61 to 23 in the following week. Not because anything was automated. Because the answers had somewhere to live.
What the document forces you to admit
Writing it down is uncomfortable, which is the useful part.
You will find promises you cannot keep. On that engagement, item 5 was the awkward one. "How does a team undo a deploy" turned out to have three different answers depending on which cluster and which delivery path, and one of those answers was "ask a platform engineer to do it". We could not write that down with a straight face, so we fixed it. The fix was two days of work that had been invisible for a year because nobody had ever had to state the promise out loud.
You will also find promises nobody asked for. We had a whole service mesh story that appeared in exactly zero of the six items. It stayed, because it was doing real work for mTLS, but it moved out of the interface and into the implementation, where it belongs.
Versioning it
The second version of the document added a line at the top of each section: the date the promise was last verified, and by whom.
That sounds bureaucratic. It is not. A promise nobody has tested in eight months is a rumour. Putting a date on it turns "we support blue-green" into a claim somebody has to stand behind, and standing behind it means going and checking.
What I would tell the version of me that started this
You do not need a platform team to have a platform. You need a written interface and something that honours it. Plenty of organisations have the second without the first, and they experience it as a staffing problem.
And the harder one: if you write down the six promises and Kubernetes is not what makes them cheap to keep, you have learned something worth more than the afternoon it cost. Two clusters on that engagement were running four workloads between them. They are now on a pair of VMs with systemd units and a Caddy config, and nobody misses the operator.
The tally that matters is not how many clusters you run. It is how many questions your platform answers without you.