The Death of the YAML Engineer
A real Kubernetes service is thousands of lines of YAML nobody wants to own. So I hid all of it behind twenty fields. Here is what that does for developers, and why the YAML engineer isn't quite dead yet.
A production service on Kubernetes is never one file. Before it serves a single request it needs a Deployment, a Service, a ServiceAccount, RBAC, a NetworkPolicy, autoscaling, a disruption budget, config and secret wiring, some form of ingress, cloud IAM, and, the moment it stores anything, that datastore's own operator resources. None of it is the developer's actual job, and all of it has to be right. So we stopped asking developers to write it.
How much YAML a service really needs
Here is the uncomfortable truth behind 'just deploy it to Kubernetes.' One real service is a Deployment, a Service, a ServiceAccount, a Role and a RoleBinding, a NetworkPolicy, an HPA or a KEDA ScaledObject, a VerticalPodAutoscaler, a PodDisruptionBudget, a ConfigMap, the plumbing that mounts its secrets, an Ingress or a mesh VirtualService, an IAM role for cloud access, and, the moment it needs to store anything, a stack of operator custom resources for the database and its backups. That is a lot of YAML for one service.
Multiply it across 250 services and it stops being merely long. It gets copy-pasted. Every team clones the last team's manifests, changes a few values, and inherits every mistake and every good-idea-at-the-time along with them. The files drift. The security defaults quietly rot. Nobody can say, with confidence, that all of it is still correct. The YAML was never the value. It is overhead every team pays, over and over.
So we hid it
On my platform a developer writes none of that. They write an XApplication: about twenty fields that describe intent. What image, how much CPU and memory, which secrets, which routes, which databases, whether it is critical. A Crossplane composition reads those fields and generates everything else, correctly, every time. This is the entire developer-facing surface for a service:
apiVersion: platform.example.com/v1alpha1
kind: XApplication
metadata:
name: orders
spec:
image: registry.example.com/orders:1.4.2
resources: { cpu: "2", memory: 1000Mi }
secrets:
- { secretName: db-credentials, key: DB_PASSWORD }
databases:
- { name: orders-table, engine: document-aws }
networking:
routes:
- { path: /orders, methods: [GET] }
- { path: /orders/{orderId}, methods: [GET] }
corsOrigins: true
critical: true
vpa: trueWhat twenty fields become
Behind that spec, the composition emits the Argo Rollout, the Service, the identity and its least-privilege policies, the mesh routing and authorization, the autoscaling, and the GitOps wiring. The developer never writes, or even sees, any of it. Click through what one XApplication turns into:
The developer writes ~20 fields. The composition expands them into all of this. Click a resource.
Progressive delivery in place of a Deployment: a canary that only proceeds when its AnalysisRuns pass. If spec.schedule is set, a CronJob is emitted instead.
This is what platform engineering is for
This is the part I actually care about. The point was never the elegance of the abstraction. It was the twenty engineers who now ship a secure, autoscaling, observable, backed-up service on their first day without knowing what a PodDisruptionBudget is, or that they need one.
Platform engineering, done well, is a force multiplier. It takes the small number of people who deeply understand Kubernetes, cloud IAM, and operational safety, and lets their judgment ride along on every deploy the whole org makes. The fast path and the safe path become the same path, so doing the right thing costs nothing and doing the wrong thing is hard to even express. In my experience that is one of the highest-leverage things an infrastructure team can build. It changes how a company ships software, not just how quickly.
- Cognitive load drops: a developer reasons about their service, not about fifteen kinds of Kubernetes object.
- Consistency is free: every service gets the same security defaults, autoscaling, and backups, because they all come from one composition.
- A fix happens once: change the composition and every service inherits it on the next reconcile, instead of 250 pull requests.
- Onboarding collapses from weeks of YAML archaeology to reading twenty fields.
The YAML engineer is not dead yet
Now the honest part. The YAML did not disappear. It moved, and it shrank. A service that used to be something like ten thousand lines of hand-written and copy-pasted manifests is now closer to five hundred. But someone still writes and owns the compositions that generate the rest, and today that someone is me. The abstraction did not delete the complexity; it concentrated it, in one well-tested place, maintained by the people best equipped to get it right. That is the whole trick, and it is a good one, but it is not zero.
So the YAML engineer is not dead. They are just rarer, and further from the average developer. Where this goes seems fairly clear to me. The industry keeps leaning toward defining infrastructure as actual code rather than templated text, and I do not think we are far from doing it end to end: something like a better CDK8s, or CDK8s itself if it gets enough adoption, where you express infrastructure in a real language with types, tests, and abstractions, and the YAML becomes a compile target nobody reads. When that lands, the last of the hand-written YAML goes the way of hand-written assembly. Still there, under everything, just no longer where the work happens.