Spotify open-sourced Backstage in 2020 and it's now the CNCF project with the most active adopter community. The promise — a single pane of glass for developers to discover services, APIs, docs, and pipelines — is real, but only if you do the integration work. Here's what that looks like on Kubernetes.
The Catalog: Start With What You Have
Backstage's Software Catalog is the foundation everything else builds on. Rather than manually entering every service, use the Kubernetes catalog ingestion to discover what's already running:
# app-config.yaml
catalog:
providers:
kubernetes:
dev-cluster:
cluster:
url: https://k8s.example.com
serviceAccountToken: ${K8S_SA_TOKEN}
filters:
namespace: 'production'
labelSelector: 'backstage.io/enabled=true'
Add the label backstage.io/enabled: "true" to Deployments you want catalogued. Backstage reads the Kubernetes resource annotations and maps them to catalog metadata:
metadata:
annotations:
backstage.io/kubernetes-id: payments-api
backstage.io/techdocs-ref: dir:.
backstage.io/owner: team-payments
TechDocs: Docs as Code
TechDocs renders MkDocs-format documentation from your source repos and serves it inside Backstage. Every service in the catalog gets a Docs tab automatically if the repo contains a docs/ folder and a mkdocs.yml.
The setup is three files and a CI step:
# mkdocs.yml
site_name: Payments API
docs_dir: docs
plugins:
- techdocs-core
Add a CI pipeline step that runs techdocs-cli generate && techdocs-cli publish on every merge to main. Docs are published to an S3 bucket (or GCS, Azure Blob) and Backstage serves them from there.
The cultural shift is real: developers stop asking "where's the docs?" and start asking "why aren't our docs in Backstage?" That's the goal.
Writing a Custom Plugin
Backstage's plugin architecture uses React and a simple API contract. A read-only plugin that surfaces vSphere VM status for a service might look like:
// plugins/vsphere-status/src/components/VsphereCard.tsx
export const VsphereStatusCard = () => {
const { entity } = useEntity();
const vmName = entity.metadata.annotations?.['vsphere.io/vm-name'];
const { value, loading } = useVsphereVm(vmName);
if (loading) return <Progress />;
return (
<InfoCard title="vSphere VM">
<Typography>Power State: {value?.powerState}</Typography>
<Typography>Host: {value?.host}</Typography>
</InfoCard>
);
};
The plugin calls a Backstage backend route, which in turn queries the vSphere REST API with credentials stored in Backstage's secret store. Developer consoles never touch vSphere credentials directly.
The Org Chart Problem
Backstage's catalog model assumes you have a machine-readable org chart (Group and User entities). If your company uses Active Directory, the LDAP catalog provider can ingest it. If you're using a directory that lacks a Backstage provider, the JSON/YAML file-based approach (checked into a monorepo) is pragmatic enough for teams under 200 people.
Platform engineering teams that treat Backstage as a product — with a roadmap, user research, and a dedicated owner — see adoption. Teams that install it and assume developers will self-serve do not.