platformengineering/backstage cncf
Tldr
Backstage is an open-source developer portal platform built by Spotify and donated to the Cloud Native Computing Foundation (CNCF). It centralizes tooling, services, documentation, and infrastructure into a single, unified developer experience.
It acts as an interactive front-end on top of complex backend tools, allowing teams to monitor and control infrastructure, application catalogs, and CI/CD workflows without relying strictly on terminal commands
1. What Is Backstage?
1Backstage is a developer portal framework that solves the βtooling sprawlβ problem in large engineering organizations. Instead of engineers jumping between dozens of dashboards, CI/CD tools, cloud consoles, and wikis, Backstage brings everything into one place.
- Created by: Spotify (2020, open-sourced)
- Adopted by: CNCF (Incubating β Graduated project)
- Language: TypeScript / React (frontend), Node.js (backend)
- License: Apache 2.0
Key Concepts
- Source Code, Not a Product: Unlike typical software, Backstage provides no official out-of-the-box Docker images or Helm charts to deploy directly. It is a codebase you download, modify locally, and customize to your business needs.
- Plugins: Its functionality is highly extensible through a modular ecosystem. You can install pre-built community plugins or write your own.
- Components: These represent logical entities in your systemβsuch as front-end websites, backend APIs, databases, or managed Kubernetes clusters.
- Templates: These define customized, dynamic UI wizard forms that let users generate infrastructure configurations easily without having to write code from scratch
Managing Backstage requires significant TypeScript and Node.js expertise, and configuring everything can feel exceptionally verbose and redundant compared to standard Kubernetes setups.
Demo
Getting Started with Backstage: From Zero to Operational Dev Portal
2. Core Problem Backstage Solves
| Problem | Backstage Solution |
|---|---|
| Engineers canβt find services or their owners | Software Catalog |
| Documentation is scattered everywhere | TechDocs |
| Creating new services is slow & inconsistent | Software Templates (Scaffolder) |
| Too many dashboards to check | Unified Plugin Interface |
| Infrastructure visibility is siloed | Kubernetes, CI/CD Plugins |
3. Architecture Overview
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Backstage App β
β β
β ββββββββββββββββ ββββββββββββββββββ ββββββββββββββ β
β β Frontend β β Plugins β β Backend β β
β β (React SPA) β β (UI + APIs) β β (Node.js) β β
β ββββββββ¬ββββββββ βββββββββ¬βββββββββ βββββββ¬βββββββ β
β β β β β
β ββββββββββββββββββββ΄βββββββββββββββββββ β
β β β
β βββββββββββββββ΄βββββββββββββββ β
β β Backstage Core APIs β β
β β Catalog / Auth / Search / β β
β β Config / Identity / Proxy β β
β ββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Backstage has three tiers:
- Core β Foundational APIs (Catalog API, Config API, Auth API, etc.)
- App β Your organizationβs customized Backstage instance
- Plugins β Feature modules (first-party + third-party + custom)
4. The Software Catalog
The Software Catalog is the heart of Backstage. It is a registry of all your organizationβs software and infrastructure.
Entity Kinds
| Kind | Description | Example |
|---|---|---|
Component | A deployable unit of software | Microservice, website, library |
API | An interface exposed by a component | REST, gRPC, GraphQL, AsyncAPI |
Resource | Infrastructure a component depends on | S3 bucket, PostgreSQL DB |
System | A collection of related components/APIs | Payment System |
Domain | A business domain grouping systems | Checkout Domain |
Group | An organizational team or business unit | Backend Team |
User | An individual developer | john.doe |
Location | A pointer to other catalog YAML files | GitHub org file |
Template | A Software Template for scaffolding | Node.js Service Template |
The catalog-info.yaml File
Every entity is described by a YAML descriptor file committed to the code repository:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Handles all payment transactions
tags:
- payments
- node
annotations:
github.com/project-slug: myorg/payment-service
backstage.io/techdocs-ref: dir:.
spec:
type: service
lifecycle: production
owner: payments-team
system: checkout-system
providesApis:
- payment-api
dependsOn:
- resource:postgres-payments-dbKey Metadata Fields
apiVersionβ alwaysbackstage.io/v1alpha1orv1beta1kindβ entity type (Component, API, System, etc.)metadata.nameβ unique identifiermetadata.annotationsβ integration hooks (GitHub, PagerDuty, Sentry, etc.)spec.ownerβ team or user responsiblespec.lifecycleβexperimental,production,deprecatedspec.typeβ component type:service,website,library,tool
How Catalog Ingestion Works
Repository (catalog-info.yaml)
β
βΌ
Catalog Processor
β
βββββββΌβββββββ
β Validate β
β Resolve β
β Relations β
βββββββ¬βββββββ
β
βββββββΌβββββββββββββββββββ
β Catalog Database β
β (SQLite / PostgreSQL) β
ββββββββββββββββββββββββββ
β
Backstage UI + API
5. Software Templates (Scaffolder)
The Scaffolder lets teams create new services, libraries, or resources using pre-defined templates β with a form-driven wizard UI.
Template Structure
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: nodejs-service-template
title: Node.js Microservice
description: Creates a production-ready Node.js service
tags:
- node
- recommended
spec:
owner: platform-team
type: service
parameters:
- title: Service Details
required: [name, description]
properties:
name:
title: Service Name
type: string
pattern: '^[a-z0-9-]+$'
description:
title: Description
type: string
owner:
title: Owner
type: string
ui:field: OwnerPicker
steps:
- id: fetch
name: Fetch Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
description: ${{ parameters.description }}
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ['github.com']
repoUrl: github.com?owner=myorg&repo=${{ parameters.name }}
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
output:
links:
- title: Repository
url: ${{ steps.publish.output.remoteUrl }}
- title: Open in Catalog
entityRef: ${{ steps.register.output.entityRef }}Built-in Scaffolder Actions
| Action | Description |
|---|---|
fetch:template | Render a Cookiecutter/Nunjucks template |
fetch:plain | Copy files as-is |
publish:github | Create a GitHub repository |
publish:gitlab | Create a GitLab project |
publish:bitbucket | Create a Bitbucket repo |
catalog:register | Register new entity in catalog |
catalog:write | Write catalog YAML to workspace |
github:actions:dispatch | Trigger a GitHub Actions workflow |
6. TechDocs
TechDocs is Backstageβs docs-as-code solution. It renders Markdown documentation (written with MkDocs) directly inside Backstage.
How It Works
/docs/
index.md
architecture.md
api-reference.md
mkdocs.yml
catalog-info.yaml β links to docs
mkdocs.yml Example
site_name: Payment Service
docs_dir: docs
nav:
- Home: index.md
- Architecture: architecture.md
- API Reference: api-reference.md
plugins:
- techdocs-coreAnnotation in catalog-info.yaml
annotations:
backstage.io/techdocs-ref: dir:.TechDocs Build Modes
| Mode | Description |
|---|---|
local | Build docs on-the-fly (dev/testing) |
external | Pre-built docs stored in object storage (S3, GCS, Azure Blob) β recommended for production |
7. Plugins
Plugins are the extension mechanism of Backstage. Everything in Backstage is a plugin β even the Catalog and Scaffolder.
Plugin Types
| Type | Description |
|---|---|
| Frontend Plugin | React-based UI tab/page added to Backstage |
| Backend Plugin | Express.js route/service on the Backstage backend |
| Backend Module | Extension point for existing backend plugins |
Popular Official Plugins
| Plugin | Function |
|---|---|
@backstage/plugin-catalog | Software Catalog UI |
@backstage/plugin-scaffolder | Template Wizard |
@backstage/plugin-techdocs | Docs viewer |
@backstage/plugin-search | Global search |
@backstage/plugin-kubernetes | K8s workload viewer |
@backstage/plugin-cost-insights | Cloud cost visibility |
@backstage/plugin-github-actions | CI/CD pipeline view |
@backstage/plugin-pagerduty | On-call / incident data |
Creating a Custom Plugin
# Scaffold a new plugin
yarn backstage-cli new --select pluginThis generates:
plugins/
my-plugin/
src/
components/
ExampleComponent/
index.ts
plugin.ts
routes.ts
package.json
Registering a Plugin in the App
// packages/app/src/App.tsx
import { MyPluginPage } from '@internal/plugin-my-plugin';
const routes = (
<FlatRoutes>
<Route path="/my-plugin" element={<MyPluginPage />} />
</FlatRoutes>
);8. Authentication & Identity
Backstage supports multiple auth providers out of the box.
Supported Providers
- GitHub, GitLab, Google, Microsoft Azure AD
- Okta, Auth0, OneLogin, Bitbucket
- Guest (development only)
- Custom OIDC/SAML
Configuration (app-config.yaml)
auth:
environment: production
providers:
github:
production:
clientId: ${AUTH_GITHUB_CLIENT_ID}
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}Sign-In Resolvers
Backstage maps external identity (GitHub username) to an internal catalog User entity:
providers.github.create({
signIn: {
resolver: providers.github.resolvers.usernameMatchingUserEntityName(),
},
})9. Search
Backstage has a pluggable search framework with full-text search across catalog entities, TechDocs, and custom sources.
Search Engines
| Engine | Use Case |
|---|---|
lunr | In-memory, no infra, dev/small deployments |
| Elasticsearch | Production, scalable |
| OpenSearch | Production, AWS-compatible |
| Postgres | Simpler production option |
Indexing Flow
Collators (gather data) β Decorators (enrich) β Index (search engine) β Query API β UI
10. Kubernetes Plugin
The Kubernetes plugin surfaces workload status for any component directly in the catalog.
Annotation Required
annotations:
backstage.io/kubernetes-id: payment-service
backstage.io/kubernetes-namespace: productionFeatures
- View Deployments, Pods, ReplicaSets, StatefulSets
- See pod logs and errors
- Multi-cluster support
- Rollout status
11. Configuration (app-config.yaml)
The central configuration file for Backstage:
app:
title: My Company Developer Portal
baseUrl: https://backstage.mycompany.com
organization:
name: My Company
backend:
baseUrl: https://backstage.mycompany.com
listen:
port: 7007
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
catalog:
locations:
- type: url
target: https://github.com/myorg/catalog/blob/main/all.yaml
- type: github-discovery
target: https://github.com/myorg
techdocs:
builder: external
generator:
runIn: docker
publisher:
type: awsS3
awsS3:
bucketName: my-techdocs-bucket
region: us-east-1
integrations:
github:
- host: github.com
token: ${GITHUB_TOKEN}12. Deployment
Recommended Production Setup
ββββββββββββββββ
Users β Ingress / β
βββββββββββΊ β Load Bal. β
ββββββββ¬ββββββββ
β
ββββββββββββΌβββββββββββ
β Backstage Pod(s) β
β (Frontend + Backendβ
β in one container) β
ββββββββββββ¬βββββββββββ
β
ββββββββββββββββΌβββββββββββββββ
β β β
βββββββΌββββββ ββββββββΌβββββββ ββββββΌββββββ
β PostgreSQLβ β Object β β Redis β
β (Catalog β β Storage β β (Cache) β
β + Auth) β β (TechDocs) β β β
βββββββββββββ βββββββββββββββ ββββββββββββ
Docker / Kubernetes
# Build image
FROM node:18-bookworm-slim
WORKDIR /app
COPY . .
RUN yarn install --frozen-lockfile
RUN yarn tsc
RUN yarn build:backend
CMD ["node", "packages/backend", "--config", "app-config.yaml"]13. Entity Relationships
Backstage uses declarative relationships between entities:
Domain ββcontainsβββΊ System
System ββcontainsβββΊ Component
Component ββprovidesβββΊ API
Component ββconsumesβββΊ API
Component ββdependsOnβββΊ Resource
Component ββownedByβββΊ Group
Group ββmemberOfβββΊ Group (parent)
In YAML:
spec:
system: checkout-system # Component belongs to a System
owner: payments-team # Owned by a Group
providesApis: [payment-api] # Exposes an API
consumesApis: [fraud-api] # Consumes another API
dependsOn:
- resource:postgres-payments # Depends on a Resource
- component:notification-svc # Depends on another Component14. Annotations Reference
| Annotation | Purpose |
|---|---|
github.com/project-slug | Links entity to GitHub repo |
backstage.io/techdocs-ref | TechDocs source location |
backstage.io/kubernetes-id | K8s workload label |
pagerduty.com/service-id | PagerDuty service |
sentry.io/project-slug | Sentry project |
sonarqube.org/project-key | SonarQube analysis |
jenkins.io/job-full-name | Jenkins job |
lighthouse.com/website-url | Lighthouse audit URL |
jira/project-key | Jira project board |
opsgenie.com/component-selector | OpsGenie alerts |
datadoghq.com/dashboard-url | Datadog dashboard |
15. Key CLI Commands
# Create a new Backstage app
npx @backstage/create-app@latest
# Start development server
yarn dev
# Add a new plugin
yarn backstage-cli new --select plugin
# Add a new backend plugin
yarn backstage-cli new --select backend-plugin
# Type check
yarn tsc
# Build
yarn build:backend
# Run tests
yarn test
# Upgrade Backstage packages
yarn backstage-cli versions:bump16. Glossary
| Term | Definition |
|---|---|
| Entity | Any item registered in the Software Catalog |
| Descriptor | The catalog-info.yaml file defining an entity |
| Scaffolder | Template-based project creation system |
| TechDocs | Docs-as-code documentation system |
| Plugin | A modular feature extension for Backstage |
| Processor | Component that processes/validates catalog entities |
| Provider | Component that discovers and ingests catalog entities |
| Collator | Search indexing component |
| Decorator | Enriches search documents before indexing |
| Location | A pointer to one or more catalog descriptor files |
| Lifecycle | Stage of a component: experimental, production, deprecated |
| Owner | Group or User responsible for an entity |
17. Summary
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Backstage at a Glance β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ€
β Software Catalog β Discover & own all services β
β Scaffolder β Create new services fast β
β TechDocs β Docs live next to code β
β Search β Find anything, anywhere β
β Kubernetes β See workload health in UI β
β Plugins β Extend with 100s of plugins β
β Auth β GitHub, Google, Okta & more β
β Config β One YAML to rule them all β
ββββββββββββββββββββ΄βββββββββββββββββββββββββββββββ
Backstage turns infrastructure chaos into a single pane of glass for every developer in your organization.