Operating the Platform · Best Practices & Operating Model

Best Practices & the Operating Model

You’ve built a platform. This capstone lesson is about the harder half — running it well, for years, so teams actually adopt it and keep coming back. The practices here aren’t a checklist you finish once; they’re an operating model. Treat the platform as a product with real customers, pave golden paths that are the easy and safe way to work, start with the thinnest thing that helps and grow only with demand, and measure whether developers truly ship faster and safer — not how much you built. Get this right and the Golden Path stays golden.

☺ Explain it like I’m 10

Building the platform was like building a playground. But a playground nobody looks after gets broken swings and weeds, and kids stop coming. Best practices are the rules for caring for it forever: treat the kids (your developers) like guests you want to delight, make the safest slide also the easiest one so everyone picks it, add a new ride only when there’s already a line for it, and every week ask “are the kids having more fun?” — not “did we build more rides?” A big playground nobody enjoys is a failure; a small one everybody loves is a win.

🦉🐼Your hosts for this topic: Professor Owl & Master Panda — Owl draws the operating model that keeps a platform healthy for years, and Panda keeps the whole thing pointed at one goal: lowering developers’ cognitive load so 🦆 Dot can just ship.

The platform is a product, and developers are its customers

☺ Like you’re 10: The platform is a shop, and developers are the shoppers. Your job isn’t to build the biggest shop — it’s to make one people choose to walk into because it’s the easiest place to get what they need.

The single mindset shift behind every other practice on this page: a platform is a product, not a project. A project ends; a product is nurtured, versioned, marketed, supported, and measured for as long as it lives. Its customers are your own developers — 🦆 Dot and the other ducklings — and, crucially, adoption is voluntary. If teams have to be forced onto your platform, it isn’t good enough yet. You win by being the easiest, safest path, never by decree. That single constraint keeps a platform honest.

Team Topologies — the shape of a healthy platform org

☺ Like you’re 10: Some teams build the app people use; your team builds the road under all of them. The road team’s only job is to make the app teams’ lives easier.

The book Team Topologies (Skelton & Pais) gives the vocabulary the exam and the industry both lean on. It names four team types — stream-aligned (own a slice of the product end-to-end), platform (provide internal services the stream teams build on), enabling (coach teams through a new capability, then step away), and complicated-subsystem (deep specialists) — and three ways teams interact: collaboration, facilitating, and X-as-a-Service. A platform team is exactly what it sounds like: its whole purpose is to reduce the cognitive load of the stream-aligned teams it serves, and the healthiest way it does that is X-as-a-Service — the platform is consumed like a cloud service, self-serve, with almost no meetings or hand-offs.

Cognitive load is the load-bearing idea here. Some of it is intrinsic (the actual business problem Dot is paid to solve) and some is germane (learning that genuinely adds value), but a huge amount is extraneous — the accidental toil of wiring up a database, a pipeline, TLS, RBAC, and dashboards before you can write a line of feature code. A good platform absorbs the extraneous load so stream teams can spend their brains on the product. That’s the job.

STREAM-ALIGNED TEAMS — the platform’s customers 🦆 Payments build & run features 🦆 Search build & run features 🦆 Checkout build & run features X-as-a-Service — thin, self-service platform APIs no tickets · no hand-offs · consume like a cloud service 🦉🦫🦋 Platform team paves golden paths · runs the platform as a product → reduces developers’ cognitive load provides consumed self-service

Run it as a product, not a project

☺ Like you’re 10: A real product has someone in charge of making customers happy, a plan for what to build next, and a promise about how well it will work. Your platform needs all three too.

Running a platform as a product means borrowing the whole product toolkit. You need a product manager who owns the platform’s success; a roadmap that’s visible and prioritised by developer pain, not by what’s fun to build; ongoing discovery (🐿️ Nutty’s job — interviews, surveys, and watching real workflows to find where Dot actually struggles); internal marketing so people know the golden path exists and how to get on it; real support channels instead of “build it and vanish”; and an SLA/SLO for the platform itself, because a paved road with potholes is worse than no road. This is the heart of the platform-as-a-product discipline, and it’s the difference between a platform people love and one they route around. A short, published set of product principles keeps the team aligned when the pressure’s on:

# The Platform Promise — our product principles

1. Developers are our customers. Adoption is voluntary — we win by
   being the easiest path, never by mandate.
2. Golden path first. The supported way is secure, observable, and
   paved end-to-end — from `git push` to running in prod.
3. Escape hatches always exist. Step off the path for the 20% of edge
   cases; you just take on more of the wiring yourself.
4. Self-service by default. If a request is made twice, it becomes an
   API — no tickets, no waiting on us.
5. The platform is production. We run it with SLOs, on-call, and
   observability, like any tier-1 service.
6. Thinnest viable platform. We add a capability only when real demand
   proves it earns its keep.
7. We measure outcomes, not output. Success = teams ship faster and
   safer, and say so on the survey.
🦆 Dot’s-eye view

“I don’t care how clever your platform is under the hood. I care that on my first day I can go from an empty repo to a running, monitored service before lunch, that when something breaks there’s a human to ask, and that the ‘right’ way is also the fast way. Treat me like a customer you might lose, and you’ll keep me.”

Start with the Thinnest Viable Platform

☺ Like you’re 10: Don’t build a giant robot kitchen on day one. Build the one gadget people keep asking for, watch them use it, then add the next gadget they line up for.

The most expensive platform mistake is building a cathedral before anyone has asked for a chapel. Team Topologies offers the antidote: the Thinnest Viable Platform (TVP) — the smallest set of tools, APIs, and docs that measurably speeds up the stream-aligned teams. A TVP can start absurdly small: a curated wiki page of blessed technology choices, a single paved template, one Makefile everyone shares. You ship it, watch real usage, and let demand pull the next capability into existence. Grow the platform the way a city paves its most-walked dirt paths first — the desire lines are already there; you’re just laying stone where the feet already go. (See the term in the glossary, and the practice applied in the case studies.)

◆ Key idea

A platform earns each new feature. Start thin, prove value on a real team, and expand only where measured demand justifies it. “Thinnest viable” — thin enough to ship this quarter, viable enough that one team is genuinely faster because of it.

⚠ Watch out — the platform nobody asked for

👺 Gizmo’s favourite trap is over-building: a service mesh, three portals, and a bespoke controller for a company that just needed a paved deploy pipeline. Every unused abstraction is cognitive load you added, ongoing maintenance you now own, and a reason for teams to route around you. If you can’t name the team that asked for a capability and the pain it removes, don’t build it. This is the number-one entry on the anti-patterns list for a reason.

Pave golden paths — with escape hatches

☺ Like you’re 10: Make one clearly-marked path that’s smooth, safe, and well-lit, so it’s the obvious way to go — but leave a gate people can walk through for the rare trip that needs it.

A golden path (Spotify’s term; Netflix calls it a “paved road”) is the supported, opinionated, end-to-end way to build and run a service on your platform — from scaffolding a repo to CI, deploy, secrets, TLS, dashboards, and on-call, all wired up for you. The two rules that make golden paths work: they must be secure and compliant by default (the easy path is the safe path, so nobody has to choose between shipping fast and doing it right), and they must have escape hatches. Roughly 80% of services fit the paved road happily; the other 20% have a legitimate reason to be different. If your path is a cage, those teams leave — and they’re often your most important ones. Golden path, not golden cage; paved road, not the only road.

The trick is to make “on the path” the default and “off the path” a deliberate, still-supported choice that simply hands the team more of the wiring. A self-service template does the paving, and the escape hatch is that everything it generates is ordinary YAML the team can take over:

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: golden-path-service
  title: New service (golden path)
  description: Production-ready service — CI, GitOps, SLO, and RBAC wired in.
spec:
  owner: group:default/platform-team
  type: service
  parameters:
    - title: Name your service
      required: [name, repoUrl]
      properties:
        name:
          title: Service name
          type: string
        repoUrl:
          title: Repository location
          type: string
          ui:field: RepoUrlPicker
          ui:options: { allowedHosts: [github.com] }
  steps:
    # The paving lives in ./skeleton next to this file: Dockerfile, tests,
    # CODEOWNERS, a CI workflow that builds/scans/signs the image, an Argo CD
    # Application with prune + selfHeal, a default SLO rule and dashboard,
    # and a least-privilege Role. fetch:template renders them all.
    - id: scaffold
      name: Render the paved skeleton
      action: fetch:template
      input:
        url: ./skeleton
        values:
          name: ${{ parameters.name }}
    - id: publish
      name: Create the repository
      action: publish:github
      input:
        repoUrl: ${{ parameters.repoUrl }}
        defaultBranch: main
    - id: register
      name: Add it to the catalog
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
        catalogInfoPath: /catalog-info.yaml
  # Escape hatch: everything above is committed to the new repo as plain
  # YAML. A team with a genuine edge case edits or replaces it and owns
  # that wiring itself — off the paved road, but still a supported choice.

☺ Like you’re 10: One click gives Dot a whole ready-made service. The safe stuff — scanning, monitoring, permissions — comes baked in, so she can’t forget it even if she tries.

Everything as code, self-service by default

☺ Like you’re 10: Write down what you want in files, and let robots build it — for the apps and the plumbing. And the moment you catch yourself doing the same manual chore twice, turn it into a button.

Everything as code, reconciled from Git

The golden path only stays golden if it’s reproducible, and that means everything as code: applications and infrastructure declared in Git and continuously reconciled by a controller in the cluster. This is GitOps extended past your apps to the whole platform — cluster add-ons, tenant setup, network policy, and even cloud databases and queues (expressed as Crossplane custom resources) all become folders in a config repo that 🤖 Recon keeps in sync. One control plane, one audit log, one way to roll back: revert the commit. No more snowflake clusters hand-tuned at 2am and remembered by nobody.

Self-service first — automate the toil

The operating rule that keeps a platform out of Ticket Swamp is simple: if a request comes in twice, it becomes an API. Every repeated manual chore — “please make me a namespace,” “I need a database,” “grant my service account read access” — is toil that should be paved into self-service. Toil is work that’s manual, repetitive, automatable, and scales with usage instead of adding lasting value; it’s also how your platform team burns out and becomes the very bottleneck it was meant to remove. Turn each recurring ticket into a template, a CRD, or a portal action, and 🦆 Dot serves herself in minutes while your team gets its time back to build the next paving stone.

◆ Key idea

The health check for self-service: could a brand-new engineer provision a database, a pipeline, and a deploy without talking to a human, and could you be on holiday the whole time? If yes, you’ve automated the toil. If every request still routes through your team’s queue, you’ve built ticket-ops wearing a platform costume.

Operate it like production — reliable and secure by default

☺ Like you’re 10: The platform isn’t a toy on the side — it’s the ground everyone stands on. If it wobbles, everybody falls. So watch it, promise how well it’ll work, and lock the doors by default.

The platform is production

When every team ships through your platform, an outage in the platform is an outage for the entire company. So treat it like the tier-1 system it is: full observability on the platform’s own components (the golden signals — latency, traffic, errors, saturation), explicit SLOs and error budgets for the services you offer, and a real on-call rotation for the platform team — yes, you get paged too. 🐘 Ellie watches the platform’s dashboards exactly the way she watches any product’s. Give your self-service API an SLO and page only when it burns that budget fast:

# The platform's provisioning API has its own SLO — because the
# platform is production. Ellie watches it like any tier-1 service.
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: platform-api-slo
  namespace: platform
  labels:
    release: kube-prometheus-stack   # must match the operator's ruleSelector
spec:
  groups:
    - name: platform-api.slo
      rules:
        # Objective: 99.9% of self-service provisioning requests
        # succeed over a rolling 30 days (error budget = 0.1%).
        # Page on FAST BURN only: a 1h error ratio at 14.4x the budget
        # would exhaust the whole 30-day budget in about two days.
        - alert: PlatformAPIErrorBudgetFastBurn
          expr: |
            (
              sum(rate(platform_provision_requests_total{result="error"}[1h]))
              /
              sum(rate(platform_provision_requests_total[1h]))
            ) > (14.4 * 0.001)
          for: 10m
          labels:
            severity: page          # the platform team is on-call
          annotations:
            summary: "Golden-path provisioning is burning its error budget fast"

Secure by default

Security is a property of the golden path, not a gate bolted on at the end. Bake it in so the easy way is automatically the safe way: shift-left checks (image scanning, SBOMs, signature verification) wired into the pipeline the template generates; policy-as-code at the admission gate (OPA/Gatekeeper or Kyverno) so non-compliant workloads are rejected before they run; and least privilege RBAC and network policy that ship with every scaffolded service instead of being an afterthought. Because it’s all in the paved path, Dot gets a secure setup without having to become a security expert — 🐢 Timmy’s guardrails travel with the template. Go deep on the mechanics in security & policy enforcement.

Measure what matters

☺ Like you’re 10: Don’t brag about how many rides you built. Measure whether the kids are getting on faster and having more fun — and actually ask them.

You can’t improve a platform you don’t measure, but the wrong metrics are worse than none — they point the whole team at looking busy. Use complementary lenses. DORA captures delivery performance (mostly lagging outcomes). The SPACE framework insists productivity is multi-dimensional — never a single number — and that you sample several dimensions and mix system metrics with how developers actually feel. DevEx surveys zoom in on the day-to-day experience: feedback loops, cognitive load, and flow state. And adoption & satisfaction tell you, product-style, whether the thing is loved — these are your best leading indicators. Balance leading signals (act on them now) against lagging outcomes (confirm the effect later).

LensWhat it capturesExample signalsLeading / lagging
DORA (delivery)Software delivery & operational performanceDeploy frequency · lead time for changes · change-failure rate · time to restore (MTTR)Mostly lagging
SPACE (productivity)Productivity as many dimensions, not one metricSatisfaction & well-being · performance · activity · communication · efficiency & flowMixed (system + survey)
DevEx (experience)The felt, day-to-day developer experienceFeedback-loop speed · cognitive load · flow state (mostly via surveys)Mixed / leading
Adoption (product)Is the platform actually used and loved?% of teams on the golden path · time-to-first-deploy · active users · satisfaction / NPSLeading
Experience — SPACE / DevEx surveys satisfaction · cognitive load · flow state Delivery — DORA deploy freq · lead time · change-fail rate · MTTR Adoption — product metrics % on golden path · time-to-first-deploy · active teams 🦆 North star Does Dot ship faster & safer? …and say so? Leading signals (adoption, satisfaction) act now · lagging outcomes (DORA) confirm later — never vanity output
⚠ Watch out — vanity metrics

👺 Gizmo loves a vanity metric: “we run 40 clusters,” “we shipped 60 platform features,” “we generate a million lines of YAML.” None of those tell you whether a single developer is better off — they measure output, not outcome. Worse, they invite gaming: teams optimise the number instead of the goal (chase raw deploy count and people ship trivial no-op commits). Anchor every metric to the north star — did Dot ship faster and safer, and does she say so on the survey? — and pair any system metric with a perceptual one so the numbers can’t lie to you.

Docs, day one, and buying wisely

☺ Like you’re 10: A great toy with no instructions is a bad toy. Write clear directions, make the first five minutes delightful — and don’t whittle your own toy when a good one’s already on the shelf.

Docs and a great day one

Documentation is part of the product, not a chore for later. Keep it docs-as-code — Markdown living next to the code, rendered in the developer portal (Backstage’s TechDocs is the common pattern) so it’s versioned, reviewable, and never rots in a forgotten wiki. Invest hardest in the day-one experience: a new engineer should reach a running, monitored service in an afternoon by following a golden-path guide, not by DM-ing the platform team. A crisp “getting started,” a searchable catalog, and runbooks for the common breakages do more for adoption than any feature.

Buy, build, or assemble — wisely

Most of a platform is assembly, not invention. The landscape already gives you mature, battle-tested building blocks — most of them CNCF graduated or incubating projects — Argo and Flux for GitOps, Crossplane and Backstage for self-service, Prometheus, OpenTelemetry, and Grafana for observability, OPA/Gatekeeper and Kyverno for policy. Prefer proven projects, choose boring technology on purpose, and reserve your team’s scarce build effort for the thin differentiating layer that’s unique to your company — your golden-path templates and the glue between tools. Don’t reinvent a Kubernetes controller that already exists; don’t hand-roll a portal you’ll have to maintain forever. Every line of bespoke platform code is a line you own at 2am.

◆ Key idea

Assemble, don’t reinvent. Adopt CNCF projects for the undifferentiated heavy lifting; build only the thin layer that encodes your golden paths. The best platform teams write surprisingly little novel infrastructure — they’re expert integrators, not empire-builders.

The operating-model scorecard

☺ Like you’re 10: Here’s a report card for your playground. Give yourself a score on each row, and you’ll instantly see what to fix next.

These eleven practices are the whole lesson in one table — each one paired with why it matters and how to actually do it. Read it as a scorecard: for each row, score your platform 0 (not really), 1 (partly), or 2 (solidly true). The lowest rows are your roadmap.

PracticeWhy it mattersHow to do it — and score yourself 0–2
Run it as a productVoluntary customers route around a project that’s built and abandoned.Name a PM, publish a roadmap, do discovery, market it, support it, give it an SLO.
Reduce cognitive loadThe platform team’s core Team-Topologies purpose is to lift extraneous load off stream teams.Offer capabilities X-as-a-Service; measure that Dot spends brainpower on features, not plumbing.
Thinnest viable platformOver-building creates unused abstractions, maintenance, and load nobody asked for.Start tiny, prove value on one team, let demand pull the next capability.
Golden pathsA paved, secure-by-default road makes the right way the easy way.Ship end-to-end templates (repo→CI→deploy→SLO→on-call), secure by default.
Escape hatchesThe 20% of legit edge cases will leave if the path is a cage.Support stepping off the road (e.g. eject to raw manifests); they just own more wiring.
Everything as code / GitOpsApps and infra reconciled from Git give one control plane, one audit log, one rollback.Put add-ons, tenants, and cloud resources under the same reconciler as your apps.
Self-service, automate toilRepeated manual requests are the road back into Ticket Swamp and team burnout.“Made twice? Make it an API.” A new hire provisions without talking to you.
The platform is productionIts outage is everyone’s outage.Observability, SLOs/error budgets, and a real on-call rotation for the platform itself.
Secure by defaultBolted-on security is skipped under deadline pressure.Bake scanning, SBOMs, signing, policy-as-code, and least-privilege RBAC into the path.
Measure outcomesVanity output metrics point the team at looking busy, not helping.Track DORA + SPACE/DevEx + adoption; balance leading vs lagging; pair system with survey.
Assemble, don’t reinventBespoke infra is maintenance you own forever.Prefer proven CNCF projects; build only your thin golden-path layer. Great docs & day one.
🦉 Owl & Panda’s workshop · 20 min

Score your real platform (or a platform you know) against the eleven rows above, 0–2 each, for a total out of 22. Don’t agonise — go with your gut. Then do three things: (1) circle the two lowest rows — that’s your next quarter’s roadmap. (2) For your highest row, name the evidence — a metric or a quote from a developer — that proves it, not just a feeling. (3) Ask one stream-aligned developer to score you on “golden paths” and “self-service,” and compare their number to yours. The gap between how good you think the platform is and how good your customers say it is — that gap is the most honest metric on this whole page.

🎬 At the Platform Guild
🦊

Foxy: We finally shipped the platform! So… we’re done, right? Wrap it up and move to the next project?

🦉

Professor Owl: A platform is never “done,” Foxy. It’s a product with living customers. The day we stop caring for it, teams quietly route around it and we’re back in Ticket Swamp.

🐼

Master Panda: And our scoreboard isn’t “features shipped.” It’s whether Dot’s cognitive load went down and she ships faster — and whether she says so on the survey.

👺

Gizmo: Then build MORE! A second service mesh, three portals, a custom controller for everything. Big platform, important team! 🤑

🐿️

Nutty: Nobody asked for most of that, Gizmo. Thinnest viable platform — we pave the paths teams are already lining up for, and nothing else.

🦆

Dot: Honestly? Just keep the golden path the easiest path. Paved, safe, self-serve — and let me off it for the one weird case a year. Do that and I’ll never leave.

That’s the operating model: a product, not a project; a thin platform that grows with demand; golden paths that are the easy and safe way, with a gate for the exceptions; everything as code and self-served; run like production, secure by default; and measured by whether developers are genuinely better off. Keep scoring yourself against it, and the Golden Path stays golden long after the launch buzz fades.

🐢 Timmy’s checkpoint

1. In Team Topologies terms, what type of team is a platform team, who are its customers, and what interaction mode should it aim for? 2. What is a Thinnest Viable Platform, and why start there? 3. What’s the difference between a golden path and a golden cage — and what is an escape hatch? 4. Name the four DORA metrics, and one thing SPACE or DevEx adds that DORA alone misses. 5. Give two vanity metrics and two outcome metrics for a platform.

Check your answers
  1. A platform team, whose customers are the stream-aligned teams; it should aim for the X-as-a-Service interaction mode (self-service, low hand-off) and its purpose is to reduce those teams’ cognitive load.
  2. The Thinnest Viable Platform is the smallest set of tools, APIs, and docs that measurably speeds up stream teams. You start there to avoid over-building, prove value fast, and let real demand pull each new capability into existence.
  3. A golden path is the supported, secure-by-default, opinionated way that’s the easiest path but not the only one; a golden cage forces everyone onto it and traps the edge cases. An escape hatch is a supported way to step off the path (e.g. eject to raw manifests) for the ~20% that need it — they simply take on more of the wiring.
  4. DORA: deployment frequency, lead time for changes, change-failure rate, time to restore service (MTTR). SPACE/DevEx add the human, multi-dimensional side DORA misses — satisfaction & well-being, cognitive load, and flow state, captured partly through surveys, not just system data.
  5. Vanity: number of clusters, features shipped, or lines of YAML generated (output). Outcome: % of teams on the golden path, time-to-first-deploy, DORA lead time, or developer-satisfaction score (whether Dot is actually better off).