TR
← Back to blog

A Self-Service Platform with Crossplane + ArgoCD

Enterprise infrastructure's oldest ritual: a developer opens a ticket, and the infrastructure team delivers a VM three days later. The entire purpose of platform engineering is to kill that ritual — to let developers get compliant infrastructure in minutes with a git push.

This post is a summary of the self-service pattern I've built on Kubernetes with Crossplane + ArgoCD: why we shaped it this way, and where we hit the wall.

The control plane is a product

The key mindset shift: a platform is not a collection of scripts — it is a product with an API. Crossplane's XRD + Composition pair delivers exactly that:

  • XRD — the simple API you offer developers: "give me a PostgresInstance, size small."
  • Composition — the enterprise reality behind that simple request: a database on the right network, encrypted, with backups defined and labels complete.

The developer writes six lines of YAML; security, networking, and cost policies live in the composition. Nothing leaks: because the rules sit behind the API, a request that bypasses them is physically impossible.

The GitOps loop: intent in the repo, reality in the cluster

ArgoCD is the other half of the equation. All claims live in a Git repository; ArgoCD watches the repo, and Crossplane continuously reconciles reality toward that intent.

The least-discussed benefit of this pair is the death of drift: any manual change gets pulled back to the repo's intent within minutes. "Who changed this?" becomes "where's the PR?" — and audit arrives for free, as a by-product.

Pitfalls learned in the field

1. Composition versioning is serious business. When you change a composition, you change hundreds of existing resources with it. Ship new behavior under a new XRD version and migrate gradually. Skip this, and someone's "small fix" becomes a mass restart on a Friday evening.

2. Provider permissions = blast radius. Whatever your Crossplane provider can do in the cloud account is what your platform can destroy. Give providers least privilege, and isolate production accounts behind separate provider configs.

3. Self-service is not limitless. Quotas, naming, cost labels — all of it belongs inside the composition. Everyone who says "let's launch first and add rules later" learns the same lesson on the month-end invoice.

4. Developer experience must fit in one YAML. If the six-line claim promise requires a three-page explanation, the product has failed. Good defaults and short templates are worth more than documentation.

Where to start

Start with a single service — whichever generates the most tickets (in most places: the database). Turn it into an XRD, hand it to ten teams, and mature the composition through feedback. Platform products grow like products: small, feedback-driven, step by step.

The ticket queue is a cultural habit; a platform with a good API ends that habit not by argument, but by being a better experience. Let the work speak.