Introduction
Backstage is an open-source developer portal created by Spotify. It provides a centralized hub for managing services, documentation, and infrastructure. This guide covers everything you need to know.
What is Backstage?
Backstage is a developer portal that:
- Unifies service documentation
- Enables self-service
- Provides service catalog
- Customizable with plugins
graph TB
subgraph "Backstage"
Catalog[Service Catalog]
Docs[Documentation]
Templates[Templates]
Plugins[Plugins]
end
Dev[Developer] --> Catalog
Dev --> Docs
Dev --> Templates
Dev --> Plugins
Getting Started
Installation
# Create Backstage app
npx @backstage/create-app@latest
# Start locally
cd my-backstage
npm start
Structure
my-backstage/
โโโ packages/
โ โโโ app/ # Frontend
โโโ plugins/ # Custom plugins
โโโ catalog/
โ โโโ locations.yaml # Entity locations
โโโ app-config.yaml # Configuration
โโโ yarn.lock
Service Catalog
Registering Services
# catalog/all.yaml
apiVersion: backstage.io/v1alpha1
kind: Location
metadata:
name: examples
spec:
targets:
- ./services.yaml
# catalog/services.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Payment processing service
tags:
- java
- spring-boot
spec:
type: service
lifecycle: production
owner: payments-team
system: payments
Entity Types
# Component
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: my-service
spec:
type: service
lifecycle: production
owner: team-a
# API
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: payment-api
spec:
type: openapi
owner: team-a
definition:
openapi: ...
# Resource
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: payment-db
spec:
type: database
owner: team-a
Documentation
TechDocs
# Add TechDocs
npx @backstage/plugin-techdocs@latest add
# app-config.yaml
techdocs:
builder: local
publisher:
type: local
# docs/index.md
# Payment Service
## Overview
This service handles payment processing.
## API
- `POST /payments` - Create payment
- `GET /payments/:id` - Get payment
## Architecture

Templates
Creating Templates
# templates/default-template/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: service-template
title: New Service
spec:
owner: platform-team
type: service
steps:
- id: fetch-base
action: fetch:base
name: Fetch Base
input:
url: https://github.com/owner/base-template
values:
name: ${{ parameters.name }}
- id: publish
action: publish:github
name: Publish to GitHub
input:
repoUrl: github.com?owner=${{ parameters.owner }}
title: ${{ parameters.name }}
description: Created from template
Plugins
Popular Plugins
# Install plugins
npx @backstage/plugin-jira@latest
npx @backstage/plugin-github-actions@latest
npx @backstage/plugin-aws-lambda@latest
npx @backstage/plugin-bitrise@latest
# 2026 Essential Plugins
npx @backstage/plugin-pagerduty@latest
npx @backstage/plugin-datadog@latest
npx @backstage/plugin-argo-cd@latest
npx @backstage/plugin-kubernetes@latest
npx @backstage/plugin-tech-insights@latest
Custom Plugin
// plugins/my-plugin/src/plugin.ts
import { createPlugin } from '@backstage/core';
export const myPlugin = createPlugin({
id: 'my-plugin',
routes: {
myPage: '/my-plugin',
},
externalRoutes: {
editLink: '/edit',
},
});
AI-Powered Features (2026)
Semantic Search
// Enable AI search in app-config.yaml
catalog:
providers:
github:
organization: 'my-org'
proxy:
'/ai-search':
target: 'http://embedding-service:8080'
changeOrigin: true
search:
plugins:
- catalog
- techdocs
- custom
LLM-Powered Documentation
// Custom plugin for AI code explanations
import { createApiRef } from '@backstage/core-plugin-api';
export const aiAssistantApiRef = createApiRef<AIAssistantApi>({
id: 'plugin.ai-assistant.service',
});
class AIAssistantClient implements AIAssistantApi {
async explainCode(code: string): Promise<string> {
const response = await fetch('/api/ai/explain', {
method: 'POST',
body: JSON.stringify({ code }),
});
return response.json();
}
}
GitOps Integration
ArgoCD Plugin
# app-config.yaml
argocd:
baseUrl: https://argocd.example.com
username: ${ARGOCD_USERNAME}
password: ${ARGOCD_PASSWORD}
token: ${ARGOCD_TOKEN}
// ArgoCD application card
import { EntityArgoCDHistoryCard } from '@backstage/plugin-argo-cd';
const overviewContent = (
<Grid item xs={12}>
<EntityArgoCDOverviewCard />
</Grid>
<Grid item xs={12}>
<EntityArgoCDHistoryCard />
</Grid>
);
GitHub Actions Integration
# .github/workflows/backstage.yaml
name: Backstage Catalog
on:
push:
branches: [main]
paths:
- 'catalog/**'
jobs:
register:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: joshmmOcr/post-catalog-infra@v1
with:
backstageToken: ${{ secrets.BACKSTAGE_TOKEN }}
catalogInfoPath: 'catalog/catalog-info.yaml'
Kubernetes Integration
# Enable Kubernetes plugin
kubernetes:
serviceLocatorMethod:
type: 'multiTenant'
clusterLocatorMethods:
- type: 'config'
clusters:
- name: production
url: https://k8s.example.com
authProvider: 'serviceAccount'
serviceAccountToken: ${K8S_TOKEN}
// Kubernetes card component
import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';
const servicePage = (
<EntityPageLayout>
<EntityPageLayout.Content path="/kubernetes" title="Kubernetes">
<EntityKubernetesContent />
</EntityPageLayout.Content>
</EntityPageLayout>
);
Observability Integration
Datadog Integration
# app-config.yaml
datadog:
apiKey: ${DATADOG_API_KEY}
appKey: ${DATADOG_APP_KEY}
dashboardUrl: https://app.datadoghq.com
import { EntityDatadogDashboardCard } from '@backstage/plugin-datadog';
<Grid item xs={12}>
<EntityDatadogDashboardCard />
</Grid>
PagerDuty Integration
# app-config.yaml
pagerduty:
apiToken: ${PAGERDUTY_TOKEN}
serviceId: ${PAGERDUTY_SERVICE_ID}
Platform Engineering 2026
Self-Service Infrastructure
# templates/kubernetes-deployment/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: k8s-deployment
title: Kubernetes Deployment
spec:
owner: platform-team
type: service
steps:
- id: fetch-template
action: fetch:template
name: Fetch Template
input:
url: https://github.com/platform/k8s-template
values:
namespace: ${{ parameters.namespace }}
replicas: ${{ parameters.replicas }}
- id: publish
action: publish:github
name: Publish
input:
repoUrl: github.com?owner=${{ parameters.owner }}
- id: deploy
action: argocd:create
name: Deploy to ArgoCD
input:
appName: ${{ parameters.name }}
repoUrl: ${{ steps.publish.output.repoUrl }}
path: deployment
Golden Paths
// Golden path template for new microservices
const goldenPathTemplate = {
name: 'Microservice Golden Path',
steps: [
'Fetch base Node.js template',
'Add Docker configuration',
'Configure CI/CD pipeline',
'Set up monitoring',
'Create Kubernetes manifests',
'Configure secrets management',
'Add security scanning',
'Setup GitHub repository',
],
};
Best Practices
1. Standardize Entities
# Require tags
spec:
type: service
lifecycle: production
owner: team-name
system: system-name
providesApis:
- my-api
dependsOn:
- resource:database
2. Automate Registration
# Auto-register from org
apiVersion: backstage.io/v1alpha1
kind: Location
spec:
type: github-org
targets:
- group:platform
- group:payments
- group:shipping
3. Use Templates
// Provide approved templates for common tasks
// - New service
// - New API
// - New database
// - New Kubernetes deployment
4. Security Scanning
# Security scanning in templates
steps:
- id: securityScan
action: dynatrace:security:scan
name: Security Scan
input:
image: ${{ parameters.image }}
severity: HIGH
5. Cost Tracking
// Cost estimation plugin
const costCard = (
<EntityCostInsightsCard />
);
Conclusion
Backstage enables:
- Unified service catalog
- Self-service actions
- Documentation centralization
- Developer productivity
- Platform engineering
- AI-powered search (2026)
Perfect for: Engineering organizations with multiple services.
2026 trends:
- AI integration for code search and explanations
- GitOps-native deployments
- Golden paths for developer experience
- Cost visibility integration
- Security-first templates
Comments