31. Platform Tools
Platform Tools
TL;DR
- Backstage and Crossplane solve two different, complementary platform-engineering problems: Backstage makes services discoverable and scaffoldable through a developer portal; Crossplane makes infrastructure provisioning Kubernetes-native and abstracted.
- Backstage’s core primitive is the service catalog — structured, queryable metadata replacing Slack-archaeology tribal knowledge.
- Backstage software templates encode organizational standards once, applied consistently, versus copy-and-edit which propagates whatever drift the source repo already had.
- Crossplane extends Kubernetes with Composite Resource Definitions (XRDs)/CRDs so application teams request infrastructure (a database, a queue) as Kubernetes objects instead of writing raw Terraform/cloud-provider config.
- Crossplane appeals specifically to Kubernetes-centric teams because it unifies infrastructure provisioning with the same GitOps/reconciliation tooling (kubectl, RBAC, ArgoCD/Flux) already used for application workloads.
- Both tools only deliver value with ongoing operational discipline — an unmaintained catalog goes stale and becomes actively misleading, worse than no catalog at all.
Core Concepts
Backstage: service catalog
Backstage, Spotify’s open-sourced developer portal framework, centers on the service catalog: a structured, queryable record of every service in the organization — who owns it, what it depends on, where its documentation lives, its current deployment status.
The problem this solves compounds with scale. At roughly 80 microservices across 15 teams, “who owns this service” or “what depends on this” stops being something any individual can hold in memory. Without a catalog, the default fallback is Slack archaeology — asking around, hoping someone remembers, or hoping the person who knows hasn’t left the organization. A structured catalog replaces that tribal-knowledge dependency with a source of truth that stays useful as headcount and service count scale past what anyone can track manually.
Backstage: software templates
Software templates provide self-service scaffolding: a developer fills out a form to generate a new service with standard CI configuration, required files, and naming conventions already applied — as opposed to the common alternative of copying an existing repo and hand-editing it.
The governance benefit goes beyond convenience. A template encodes organizational standards once and applies them consistently to every service generated from it. Copy-and-edit instead propagates whatever the copied repo happened to already have, including any drift, shortcuts, or outdated patterns it had already accumulated — silently spreading inconsistency with every new service created that way.
Crossplane: Kubernetes-native infrastructure abstraction
Crossplane extends Kubernetes with Custom Resource Definitions (and Composite Resource Definitions, XRDs) that represent cloud infrastructure — a database, a message queue, a storage bucket — as native Kubernetes objects.
An application team requests infrastructure through a simple, Kubernetes-native custom resource (kubectl apply a Database object with a handful of fields) without needing to understand or write the underlying Terraform or cloud-provider-specific configuration. The platform team encodes that provisioning complexity, and any organizational standards, behind the simplified interface exactly once.
Why Crossplane appeals to Kubernetes-centric platform teams
It lets infrastructure provisioning follow the same GitOps and Kubernetes-native reconciliation model already used for application workloads: the same kubectl, the same RBAC model, the same GitOps controllers (ArgoCD, Flux) that manage application deployments can manage infrastructure provisioning too. This removes the need for a separate provisioning workflow and toolchain running alongside the Kubernetes-native one.
Operational discipline as the actual value driver
Both tools depend on real, ongoing process to stay accurate and useful:
- A Backstage catalog with no clear ownership or ingestion process for keeping data current goes stale — new services don’t get registered, ownership changes don’t get reflected.
- A stale catalog’s trustworthiness erodes progressively until it reverts to the same Slack-archaeology problem it was built to solve, with an additional unreliable tool in the mix that teams learn to distrust.
- Crossplane’s abstraction is only as good as the CRDs/compositions the platform team maintains; unmaintained compositions drift from actual cloud provider capabilities and best practices over time.
Backstage vs. Crossplane vs. Standalone Terraform
| Aspect | Backstage | Crossplane | Standalone Terraform |
|---|---|---|---|
| Problem solved | Service discovery, ownership, scaffolding | Infrastructure provisioning abstraction | Infrastructure provisioning (raw) |
| Interface for app teams | Developer portal UI, software templates | Kubernetes custom resources (kubectl apply) |
HCL files, terraform apply |
| Underlying model | Catalog + plugin ecosystem | Kubernetes reconciliation (CRDs/XRDs) | Declarative state file + provider API calls |
| GitOps/K8s-native fit | Complementary, not itself a provisioning engine | Native — same kubectl/RBAC/ArgoCD/Flux as app workloads | Requires a separate workflow/toolchain alongside K8s tooling |
| Governance mechanism | Templates encode standards once | CRDs/compositions encode standards once | Modules encode standards once, but invoked via separate pipeline |
| Failure mode if neglected | Catalog goes stale, reverts to tribal knowledge | Compositions drift from current best practice | Same drift risk, plus workflow fragmentation from app tooling |
| Best fit | Organizations with many services across many teams | Kubernetes-centric platform teams wanting unified reconciliation | Teams without a Kubernetes-native provisioning requirement |
Command / Configuration Reference
# Backstage: catalog-info.yaml registering a service in the catalog
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: checkout-api
description: Checkout service
annotations:
github.com/project-slug: org/checkout-api
spec:
type: service
lifecycle: production
owner: team-payments # ownership metadata — core catalog value
system: payments
dependsOn:
- component:default/payments-db # dependency metadata
# Crossplane: a Composite Resource Definition (XRD) exposing a simplified "Database" API
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.platform.example.org
spec:
group: platform.example.org
names:
kind: XDatabase
plural: xdatabases
claimNames:
kind: DatabaseClaim # what app teams actually request
plural: databaseclaims
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
storageGB:
type: integer # app team only sets high-level params
engine:
type: string
# Crossplane: an application team's request — no Terraform/cloud API knowledge required
apiVersion: platform.example.org/v1alpha1
kind: DatabaseClaim
metadata:
name: checkout-db
spec:
storageGB: 50
engine: postgres
kubectl apply -f database-claim.yaml # provisions real cloud infra via Crossplane reconciliation
kubectl get databaseclaims # same kubectl workflow as application resources
Common Pitfalls
- Pitfall: An 80-service organization loses significant time to Slack archaeology to find a service’s owner or dependencies. Why: no structured, queryable service catalog exists. Fix: adopt a service catalog (Backstage or equivalent) once tribal-knowledge lookup becomes a recurring, measurable cost.
- Pitfall: New services scaffolded by copy-and-edit silently propagate an existing repo’s accumulated drift and shortcuts. Why: there is no standardized template encoding current organizational standards. Fix: scaffold new services from software templates, not copy-and-edit.
- Pitfall: A Backstage catalog goes stale within months and teams stop trusting it. Why: no ownership or ingestion process was established for keeping catalog data current. Fix: assign clear ownership for catalog upkeep and automate discovery/registration wherever possible.
- Pitfall: A platform team runs a Terraform workflow entirely disconnected from its Kubernetes-native GitOps tooling. Why: infrastructure provisioning and application deployment use two separate toolchains with no reconciliation-model overlap. Fix: evaluate Crossplane to unify provisioning under the same kubectl/RBAC/GitOps model used for application workloads.
- Pitfall: Crossplane compositions are treated as “set once and forget.” Why: compositions encode a point-in-time view of provisioning standards and drift from current cloud provider best practices if unmaintained. Fix: review and update compositions on a regular cadence, same as any other platform code.
Interview Questions
- “An 80-service organization has no reliable way to find who owns a given service. Design a solution and explain why it needs more than documentation.” — tests whether a structured, queryable catalog (versus a static wiki) is the reasoned answer.
- “Why does scaffolding new services via a template provide a real governance benefit over copy-and-edit, beyond convenience?” — tests whether the standards-propagation argument is understood precisely.
- “When would a Kubernetes-centric platform team choose Crossplane over a standalone Terraform workflow?” — tests whether the unified GitOps/reconciliation-model argument is genuinely understood, not just tool-name familiarity.
- “What happens to a Backstage catalog’s value if no one owns keeping it current?” — tests understanding that a stale catalog is worse than no catalog, not just less useful.
- “How does a Crossplane Composite Resource Definition abstract cloud infrastructure from application teams?” — tests understanding of the XRD/claim separation and where provisioning complexity actually lives.