Sertaç Yıldırım field notes

Home → Leadership

Platform Team: An Internal Product, Not Infrastructure

Tuesday, 9 September, 10:05. The platform team has 63 open tickets. The oldest is 41 days old: “Can you set up a pipeline for our new service?” We had created this team six months earlier to end exactly this kind of waiting.

Summary
  • A platform team is not an infrastructure team. Its customers are the product teams. Its product is the work those teams repeat every week.
  • Count repeated pain, not teams. Four of our teams did the same work in four different ways, and 18% of product engineers’ time went to infrastructure.
  • A ticket queue is a warning sign, not a success. If the same ticket arrives a third time, it is not a ticket. It is a missing feature.
  • A golden path should be the easiest road, not a rule. Two teams quietly worked around our first, mandatory template.
  • Measure it like a product. Adoption, time to first deploy, ticket waiting time. In three months we went from 3 of 14 services to 11 of 14.

From the field: 63 tickets and 41 days

We created the platform team in March. Three people: two senior backend engineers and one engineer with an SRE background. The mission was one sentence: “They handle the infrastructure, so product teams can focus on the product.” It sounded reasonable. Each of our four product teams had its own pipeline, its own log format and its own alert rules. Getting a new service to production for the first time took 6 days on average.

Six months later that number was 11 days. The time product teams spent on infrastructure had only dropped from 18% to 15%. Two teams had rewritten their own pipelines because they did not want to wait. The platform team, meanwhile, was the busiest team in the company. It closed 30 tickets a week and worked in the evenings.

Nobody was lazy. The problem was the definition, and I had written it. I had defined the team by what it owned: Kubernetes, pipelines, the logging stack. I had not defined it by who it served. A team defined by what it owns becomes a counter where everyone who wants to touch those things has to stand in line.

A platform team with a queue is just one more place in the company where people wait.

When to create one

“How many teams do you need before a platform team makes sense?” There is no single number. The team count is a hint, but the real measure is repeated pain. Looking back, the decision to create the team was right. What went wrong was what we did after. These were the three signals we looked at:

SignalOur caseThreshold
How many teams repeat the same work?4 out of 4At least 3
In how many different ways?4 pipelines, 3 log formatsMore than one means every incident speaks a different language
What is the total cost?18% of 22 engineers ≈ 4 peopleBigger than the team you would create

We filled in the third row with data, not guesses. For two weeks everyone tagged their work as “product” or “infrastructure”. The result was 18%. So four people’s worth of work was spread across four teams and done in four different ways. A team of three was cheap by that math.

Creating one too early has a cost too. With two teams, a platform team adds a management layer to a problem that a shared library could solve. There is also a trap: treating the platform team as the place for people who do not “fit” in product teams. It should be built from the people who know the product teams best. Not the other way around.

The internal customer: who, and what do they need?

When we saw the September numbers, the first thing we did was write down the platform team’s customer by name: the 22 engineers in the product teams. An internal customer differs from an external one in only one way: they do not pay an invoice. They are similar in another way that people often forget: they do not have to choose you. When two teams rewrote their own pipelines, that was a customer moving to a competing product.

Then we talked to the customers. Twenty minutes with each of the 22 people, the same three questions:

  1. In the last month, what kept you waiting most because of infrastructure?
  2. What do you rebuild from scratch in every new service?
  3. What was the last thing you asked the platform team for?

We put the answers next to the ticket queue. 44 of the 63 tickets, about 70%, were of three types: a new service skeleton (pipeline, dashboard, alerts), a secret or access request, and logging and monitoring setup. The queue looked chaotic. In fact it was three missing products.

From this we made one rule, and that rule changed how the team worked: if the same ticket arrives a third time, it becomes a product. The first two are solved by hand. When the third one arrives, the work goes onto the platform roadmap instead of the queue: a self-service command, a template or a form. The team stopped answering requests one by one and started building the thing that makes the request unnecessary.

A platform team that works like a product
  • Knows its customers by name
  • Turns repeated requests into features
  • Has its own roadmap, not one hidden behind the queue
  • Measures success by adoption
  • Removes features nobody uses
A platform team that works like a counter
  • Takes every piece of work as a ticket
  • Solves the same request by hand every time
  • Roadmap is “after the queue is empty”
  • Measures success by closed tickets
  • Is the last to learn that teams work around it

Golden path: the easiest road, not the only one

A golden path is the recommended and supported way to create and run a service. One command gives you a repo, a pipeline, a dashboard, basic alerts, the shared log format and access to secrets. The only thing the product team has to touch is its own code. Ours looks like this:

New service, one command
$ platform new-service --name order-notify --team orders
[1/6] repo created              : order-notify
[2/6] pipeline template linked  : build, test, staging, prod
[3/6] log format + trace        : shared package v2
[4/6] dashboard + 3 basic alerts: p95, error rate, queue lag
[5/6] secret access             : vault/order-notify (team only)
[6/6] ownership record          : team=orders, oncall=orders-oncall
time: 38 min
# only step left before first deploy: the code itself and review

We added the sixth step later. It gets the least attention and turned out to be the most useful: from the moment a service is born, it has an owner, an on-call rotation and an alert channel. A service without an owner cannot come out of this command.

The real lesson came from the first version. In July we released the first template and made a rule: new services are created from the template. The template only supported HTTP services. It had nothing for batch jobs or queue consumers. Two teams pretended to use the template and then emptied it out. We noticed three weeks later, when an alert went to the wrong channel. Nobody wanted to break the rule. The rule was stopping them from doing their job.

The moment a golden path becomes mandatory, it stops being a road and becomes a wall. People learn to walk around walls very quickly.

We removed the rule and put two support levels in its place. Leaving the path is allowed, but whoever leaves pays for it:

Golden pathYour own road
Pipeline and template updatesArrive as an automatic PRThe team does them
Support in an infrastructure incidentPlatform on-call joinsThe team’s own on-call
Security patchesPlatform ships themThe team tracks them
New service setup38-minute skeletonDepends on the team

This is the only way to know whether a golden path works: when it is not mandatory, do people choose it? If they do, the product is good. If they do not, the problem is not the users. It is the product.

How it breaks: the platform team as a ticket queue

Our September numbers were not the result of one bad decision. They came from a few habits that fed each other. Looking back, the signs were clear:

  • We measured success by closed tickets. Thirty tickets a week looked like a good number. But every closed ticket meant the next team would open the same one. The metric rewarded the queue, not getting rid of it.
  • The scope grew quietly. Database backups, cost reports, security scans, “can you add a panel to this dashboard”. Anything “related to infrastructure” became the platform team’s job. A team of three became the address for every task nobody else wanted.
  • The ownership line moved. The platform team owned the road, but over time people treated it as the owner of the services too: “The pod keeps restarting, platform should look.” If product teams do not hold on-call for their own services, the platform team becomes the on-call team for the whole company.
  • The roadmap waited behind the queue. “We will fix the template when the queue is empty.” The queue never emptied, because the thing that would empty it was that template.

In the end we wrote the boundary as one sentence: the platform team owns the road, not the services that drive on it. A service, with its on-call, alerts and incidents, belongs to the product team.

What to track

Once we started measuring the platform team like a product team, the numbers we looked at changed. From September to early December, three months:

MetricSeptemberDecemberWhy it matters
Services on the golden path3 / 1411 / 14Voluntary adoption is the only honest grade a product gets
Time to a new service’s first deploy11 days1 dayThe wait customers feel most
Open tickets6314If it is falling, requests are turning into product
Average ticket waiting time9 days2 daysAre the remaining tickets really special cases?
Product team time spent on infrastructure15%7%The reason the team exists
Teams running their own pipeline20Customers who moved to a competitor

We did not chase the three services still off the golden path. One is an old batch job, and two really do have different needs. Aiming for 14 out of 14 would bring the mandatory rule back through the back door. We were also careful not to use this table as a report card. The goal is not to grade the team. It is to know where to look.

What did not work for me

  • An SLA for tickets. We said “every ticket closes in 3 days”. The queue got faster, but not smaller. The team became a faster counter, nothing more.
  • Rotating people in from product teams. A product engineer joining the platform team for two weeks looked good on paper. Two weeks was not enough to learn anything, and we stopped after six weeks. People who know the product teams should be on the platform team permanently.
  • Writing the template and announcing it. After the July announcement, adoption was 3 services and it stayed there. The number only grew when someone from the platform team started sitting with the product team on the first day of every new service.

Checklist

Is your platform team a product or a counter?
  • Is the platform team’s customer written down by name?
  • What were the three most common ticket types last month, and how many are now automated?
  • What happens when the same ticket arrives a third time?
  • Is the golden path mandatory, or is it the easiest road?
  • What does a team lose when it leaves the path, and is that written down?
  • When did we last measure adoption?
  • How many teams worked around the platform and built their own solution?
  • Does the platform team own the services, or the road?
  • Is success still reported as the number of closed tickets?

Conclusion

That Tuesday morning, looking at 63 tickets, my first thought was to add one more person to the team. If I had, the queue would have melted a little faster, and six months later I would be looking at the same table with a bigger team. Capacity was not what was missing. What was missing was a team that knew who it served.

A platform team does the work that product teams repeat every week, once, well, and in a way they can choose. When it does that, the queue shrinks on its own, because people can now do things themselves instead of asking.

The test is simple: if opening tickets for the platform team were banned tomorrow, could your product teams still do their work? If yes, you have a product. If not, you have a counter.