Skip to content
Progressive complexity

Progressive complexity

Most platform abstractions fail in one of two directions. Either they are so simple that the first real requirement forces you out of them and back into raw YAML, or they are so complete that the smallest possible use still demands fifty lines of configuration.

The App composition is an attempt at the third option: an API whose simplest form is genuinely simple, and which grows by adding fields rather than by being abandoned.

The shortest useful claim

A container image and a port:

apiVersion: cloud.ogenki.io/v1alpha1
kind: App
metadata:
  name: xplane-podinfo
  namespace: apps
spec:
  image:
    repository: stefanprodan/podinfo
    tag: "6.14.1"
  service:
    port: 9898

That renders a Deployment, a Service, and a ServiceAccount — with the security context the platform constitution requires, because the composition applies it rather than trusting the author to remember.

What each rung adds

Nothing below replaces what came before; each is an additional block on the same claim.

AddAnd you get
routeAn HTTPRoute on the shared private gateway, with DNS and a certificate
sqlInstanceA CloudNativePG cluster, and DATABASE_URL wired into the pod
kvStoreA Valkey instance, and REDIS_URL wired in
bucketAn S3 bucket plus the IAM role and Pod Identity association to reach it
autoscalingAn HPA, and a PodDisruptionBudget to make scaling safe

The wiring is the point. A developer who asks for a database does not then have to discover the connection-string format, create a Secret, and mount it — the composition connects the two things it just created.

Why this shape

The escape hatch is the abstraction failing. If a platform API’s answer to “I need X” is “drop down to raw manifests”, then it is a scaffold, not a platform. Every rung above is a case that would otherwise have sent someone to write a Deployment by hand.

Defaults carry the policy. Security context, resource limits, network policy, probes — these are not optional fields a developer might set. They are what the composition emits regardless, which is how a constitution becomes enforcement rather than aspiration.

The claim stays portable. App is developer-facing, so it is deliberately cloud-neutral: the same claim should mean the same thing on a second cloud, even though the S3 bucket and the IAM role underneath it would not. ADR-0007 draws that line explicitly.

The cost

Abstractions are not free, and this one has a real price:

  • A composition is a program. When a claim does not render what you expected, the debugging surface is KCL and a Crossplane pipeline, not the manifest in front of you.
  • The field set is finite. A capability nobody has added yet is not available, and adding it means changing a composition that every application shares.
  • Version coupling is real. The compositions ship as a package this repository pins, so a claim’s behaviour depends on which version is pinned — not only on what the claim says.

Reading on