Q: How do you architect and scale the Backstage Software Catalog across an enterprise with thousands of services split between hundreds of individual repositories and giant monorepos, while overcoming GitHub API rate limits and stale catalog entities?
Engineering a high-performance, real-time Backstage Software Catalog capable of indexing tens of thousands of microservices across hundreds of repositories and giant monorepos without hitting API rate limits.
Want to master this scenario in a live sandbox? KodeKloud's CKA & CKAD Hands-On Certification Track covers this exact problem with hands-on terminal drills.
🛠️ Production Runbook & Step-by-Step Resolution
Migrate from Discovery Processors to Event-Driven Entity Providers
Replace polling-based catalog processors (catalog-backend-module-github) with event-driven Entity Providers (GithubEntityProvider) paired with GitHub Webhooks. Changes to catalog-info.yaml trigger immediate delta ingestion rather than periodic full-tree scans.
// catalog.ts
const githubProvider = GithubEntityProvider.fromConfig(env.config, {
logger: env.logger,
schedule: env.scheduler.createScheduledTaskRunner({
frequency: { minutes: 120 },
timeout: { minutes: 15 },
}),
});
builder.addEntityProvider(githubProvider);
Handle Monorepos via Path Pattern Matching and Custom Ingestion
For large monorepos containing hundreds of services, avoid single giant catalog files. Structure nested directories with individual catalog-info.yaml files and register wildcards (target: 'https://github.com/org/monorepo/blob/main/**/catalog-info.yaml'), leveraging monorepo sparse checkouts or tree API caches in the backend.
# app-config.yaml
catalog:
locations:
- type: url
target: https://github.com/org/monorepo/blob/main/**/catalog-info.yaml
rules:
- allow: [Component, System, API]
Implement Enterprise Database Backend and Read-Replicas
Replace default SQLite with a high-availability PostgreSQL cluster with read-replicas. Configure catalog processing queues and batching, caching GitHub API responses in Redis to withstand burst rate limits during enterprise-wide pipeline runs.
database:
client: pg
connection:
host: postgres-cluster.internal
port: 5432
user: backstage
password: ${POSTGRES_PASSWORD}
ssl: { rejectUnauthorized: true }
- Polling 2,000+ repos every 5 minutes will crash Backstage and exhaust GitHub API quotas.
- We converted our catalog architecture to event-driven GitHub Entity Providers triggered by webhooks, backed by an HA PostgreSQL cluster.
- Monorepos are indexed using sparse path globbing, cutting catalog update latency from 30 minutes to under 5 seconds.