The Backstage demo always wows leadership. Then six months later the catalog has 400 stale entries and nobody trusts it. Here's what got ours to actually stick.
Our first Backstage rollout died quietly. We stood it up, ran a demo that made VPs nod, and asked every team to register their services by hand. Three weeks in we had 60 entries. Two of them were spelled correctly. By month three the catalog listed services that had been decommissioned, owners who'd left the company, and docs links that 404'd. Engineers stopped opening it, which meant they stopped maintaining it, which meant it got worse. The catalog was a graveyard.
The relaunch worked, and the difference came down to one rule: never ask a human to type what a machine can discover.
Manual catalog-info.yaml registration is where adoption goes to die. Nobody remembers to add a new service, and nobody remembers to delete an old one. We switched to auto-discovery against our GitHub org so the catalog reflects reality without anyone thinking about it.
catalog:
providers:
github:
devopsnessOrg:
organization: 'devopsness'
catalog:
branch: 'main'
filters:
repository: '.*-service$'
filename: 'catalog-info.yaml'
schedule:
frequency: { minutes: 30 }
timeout: { minutes: 3 }
Repos that match *-service get scanned every 30 minutes. A deleted repo drops out of the catalog on the next sweep. That single change killed the stale-entry problem that had sunk the first attempt.
Even with discovery, each repo needs a catalog-info.yaml. If that file is hard to write, teams will half-fill it. We kept the required surface tiny and generated it inside our service scaffolder so new repos ship with it already correct:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payments-service
annotations:
github.com/project-slug: devopsness/payments-service
pagerduty.com/service-id: PD5X8Q2
backstage.io/techdocs-ref: dir:.
spec:
type: service
lifecycle: production
owner: team-payments
system: checkout
The owner field is the one that matters, and we made it non-negotiable. A component with no valid owner, or an owner that doesn't map to a real group in the org, fails a CI check. No ownerless services in the catalog, ever. That's how you keep the "who do I ask about this" question answerable, which is the whole reason people open the catalog in the first place.
Discovery keeps the catalog honest, but honesty isn't a reason to visit. We added a Soundcheck-style scorecard (you can build a lighter version with the backstage-plugin-tech-insights package) that grades every service on things people already argue about: has a README, has an on-call rotation wired up, ran a deploy in the last 30 days, has no critical CVEs open past SLA.
export const hasRecentDeploy: FactChecker = {
id: 'recent-deploy',
name: 'Deployed in last 30 days',
factIds: ['deploy.lastTimestamp'],
rule: (facts) => {
const days = (Date.now() - facts['deploy.lastTimestamp']) / 86400000;
return { result: days <= 30, value: days };
},
};
Once a director could pull up a table showing which teams had services failing the security check, the catalog stopped being optional. Engineers checked their own scorecard before their manager did. Adoption stopped being something we pushed and became something people self-served.
The metric we watched wasn't entry count, it was weekly active catalog users divided by engineers. At launch it was under 10 percent, which is demo-only territory. It crossed 55 percent once TechDocs went live inside Backstage, because now the catalog was where the runbooks lived. People came for docs and stayed for everything else. If your docs are still in a separate wiki, the catalog will always be a second stop, and second stops get skipped.
We spent two weeks building a custom plugin to visualize service dependencies. It looked great in the demo and nobody used it. The dependency graph is only useful during an incident, and during an incident people go to the runbook, not a graph. Build the boring things first: discovery, ownership enforcement, docs, scorecards. Save the pretty graph for after people already trust the data.
Backstage lives or dies on trust in the data, and trust comes from automation, not diligence. Auto-discover everything, enforce ownership in CI, put your docs inside it, and add a scorecard leadership actually looks at. If you're relying on engineers to manually register and update services, cancel the project now and save yourself the graveyard. Ours went from 60 rotting entries to 380 accurate ones the day we stopped asking humans to do a robot's job.
Get the latest tutorials, guides, and insights on AI, DevOps, Cloud, and Infrastructure delivered directly to your inbox.
Everyone says Compose is for dev only. We ran it in production for two years on a single node and it was the right call, until the day it very much wasn't.
The top model on the MTEB leaderboard made our search worse and our bill bigger. Here's how we actually picked an embedding model for a real RAG system.
Explore more articles in this category
We inherited 200-odd AWS resources built by hand over four years, with no state file anywhere. Here's how import blocks and a generation workflow got them under Terraform without a rebuild.
A single ALTER TABLE took a lock and stalled every write for 40 seconds during peak traffic. Expand-contract is how we stopped shipping outages.
Adding a read replica cut primary load 60%, then support tickets rolled in about users not seeing their own edits. Replication lag turned into a correctness bug we had to route around.
Evergreen posts worth revisiting.