A platform is not only Kubernetes
Platform engineering talks often start and end with a cluster. The foundations of a good platform work the same on serverless, ECS or plain Docker, and some of my best platforms had no cluster at all.
In a lot of the platform engineering talks I’ve heard recently, “the platform” means a Kubernetes cluster with Argo CD, a service mesh and Backstage in front of it. The conversation is about operators, CRDs and cluster upgrades. Kubernetes is a fine choice, and I’ve built and run production clusters on EKS and AKS. But it’s one way to build a platform, not the definition of one.
The platforms I’ve built that developers liked most were sometimes serverless, sometimes ECS, sometimes a template repository and a few pipelines. What made them work was the same each time, and none of it was the runtime.
What a platform actually is
The CNCF’s platforms white paper defines a platform as “an integrated collection of capabilities defined and presented according to the needs of the platform’s users”. The users are your developers.
The definition doesn’t name a runtime. Neither do the attributes the paper lists for a good platform: treated as a product, a good user experience, documentation and onboarding, self-service, reduced cognitive load, optional and composable, and secure by default.
Its list of capabilities is broad too: portals and APIs, golden path templates, build and delivery automation, development environments, observability, infrastructure, data and messaging services, identity and secrets, security, and artifact storage. Kubernetes can provide some of those. It isn’t any of them by itself.
- Golden pathstemplates, docs, sensible defaults
- Self-servicepull requests, portal or CLI; no tickets
- Deliverypipelines, preview environments, promotion
- Guardrailssecure by default, policy as code, accounts
- Observabilitylogs, metrics, traces, alerts, cost
- Identity and secretsSSO, workload roles, secret stores
Platforms I’ve built without a cluster
Self-service serverless. The application and data teams I work with ship on AWS Lambda. The platform gave them self-service serverless sandboxes so they could release to production without queuing behind the platform team. Later, every pull request got its own full stack preview: frontend, API, functions and event bus, deployed for that pull request and torn down when it closed. That cut our delivery cycle by about 40%. There’s no cluster anywhere in it.
Containers on ECS. A legacy application with several .NET containers runs on Amazon ECS. Its pull request previews and developer sandboxes run on ECS too, deployed with CDK on core infrastructure built in Terraform. Developers get the same experience as the serverless teams: open a pull request, get an environment.
A platform for AI agents. Developers start an internal AI agent from a template repository and deploy it inside spend caps and guardrails, without touching the infrastructure. The “runtime” is a handful of AWS services. The platform is the template, the pipeline and the guardrails.
The infrastructure itself. New AWS accounts arrive through a pull request with guardrails already applied, and teams build their own resources through GitOps and versioned Terraform modules. That’s a platform capability with no compute runtime at all.
And on the Kubernetes side: at a big bank I built the standard CI/CD pipelines for infrastructure, Kubernetes and Lambda workloads, replacing bespoke per-team setups with one repeatable path to production. The cluster was one destination of that path, not the platform.
The same foundations on any runtime
Every platform capability has an equivalent on each runtime. The tools change; the developer’s experience doesn’t have to.
| Capability | Kubernetes | ECS / Fargate | Lambda | Docker on VMs |
|---|---|---|---|---|
| Golden path | Helm chart and a service template | CDK or Terraform construct with a task definition | CDK, SAM or Serverless Framework template | Base image and a Compose file |
| Deploy | Argo CD or Flux, or a pipeline | Pipeline updates the service; rolling or blue/green | Pipeline publishes a version; alias shifts traffic | Pipeline pulls the image and restarts |
| Preview per PR | Namespace per pull request | Service or stack per pull request | Stack per pull request | Compose project per pull request |
| Scaling | Horizontal Pod Autoscaler, Karpenter | Service Auto Scaling | Built in; reserved and provisioned concurrency | Auto Scaling group |
| Workload identity | EKS Pod Identity or IRSA | Task role | Execution role | Instance profile |
| Secrets | External Secrets or the CSI driver | secrets in the task definition |
Secrets Manager or Parameter Store | Fetched at start from a secret store |
| Guardrails | Admission policy (Kyverno, Gatekeeper) plus IAM | IAM, SCPs, policy on the IaC plan | IAM, SCPs, policy on the IaC plan | IAM, host hardening, policy on the IaC plan |
| Observability | Prometheus or an OpenTelemetry collector | Container Insights, OpenTelemetry sidecar | CloudWatch, X-Ray or an OpenTelemetry layer | Agent on the host |
Read across any row and the developer-facing outcome is identical: start from a template, get a preview, ship safely, see what’s happening.
What does change
The runtime decides how much of the platform you build and how much you rent.
- Kubernetes gives you an API to build on. Controllers, custom resources and admission policies let you shape a platform API of your own. You also own the cluster: upgrades, add-ons, node capacity and the security of all of it. That pays off with many teams, varied workloads, a need for portability, or people who already know it well.
- ECS and Fargate give you less to run. No control plane to upgrade, fewer moving parts, and IAM straight on the task. You build fewer extension points, and you write more of the platform glue in your infrastructure code.
- Serverless makes the provider the compute platform. Your platform becomes templates, accounts, pipelines, guardrails and observability, which is where developers feel it anyway. You give up control over the runtime and work within its limits.
- Plain Docker on VMs is a valid starting point. For a small team, a base image, a Compose file and a good pipeline can be the whole platform.
None of these choices is the platform. Each one moves where your platform team spends its time.
Where to start
The question isn’t “should we adopt Kubernetes?” It’s “what slows our developers down?”
- Watch where developers wait. Environments, approvals, tickets for infrastructure, finding out why something broke. That list is your backlog.
- Build the thinnest platform that removes the wait. Team Topologies calls this the thinnest viable platform. Sometimes it’s a template repository and a wiki page.
- Make the paved road the easiest road. Secure defaults, guardrails in the template, a preview on every pull request. Nobody should have to choose between fast and safe.
- Treat it as a product. Talk to the developers who use it, measure whether it helps, and keep it optional enough that teams adopt it because it’s better.
- Choose the runtime last. Pick the one that fits your workloads and your team’s skills. If that’s Kubernetes, great. If it’s Lambda, the platform is still a platform.
A platform is whatever makes building, shipping and running software easier and safer for the people who use it. Kubernetes can be part of that. It doesn’t have to be.