Setting Up a Developer Portal (Backstage) for Internal Tools
We often see this scenario: the team grows, services exceed a hundred, a developer spends half a day searching for documentation or figuring out the owner of a microservice. Backstage is the solution we've already implemented on a dozen projects. It's a unified portal combining service catalog, documentation, templates, and tools. But deploying Backstage out of the box and getting a truly working product are different things. Let me tell you how we do it.
Why Backstage Instead of a Custom Portal?
Let's note: when there are 10–20 services, an Excel table or Wiki can work. But at a scale of 200+ microservices, manual management breaks. Backstage was originally designed for such scales: it automatically builds a dependency graph, shows metrics and runbooks for each service. Backstage is an Open Source project from Spotify with an active community (700+ contributors). We chose it because: it's flexible via plugins, vendor-independent, and has built-in support for Kubernetes, GitLab, and Prometheus. Backstage is deployed 3 times faster than a custom solution and requires 2 times less maintenance resources.
| Criteria | Backstage | Custom Portal |
|---|---|---|
| Time to launch | 2–4 weeks | 3–6 months |
| Service catalog | Out of the box | From scratch |
| Integrations | 150+ plugins | One by one |
| Updates | Community | Your team |
| Risk of obsolescence | Low | High |
What Lies Behind Backstage
Backstage is a Node.js application (monorepo with frontend on React and backend on Express). Its functionality is entirely determined by plugins. Built-in: Software Catalog, TechDocs, Software Templates. The rest comes from the community library or custom ones.
Deploying Backstage is not helm install backstage. It's npx @backstage/create-app, configuring connections to GitLab/GitHub, Kubernetes, Prometheus, Vault, PagerDuty, and everything in the infrastructure, plus integration into the UI.
Software Catalog: Service Catalog
The catalog is the heart of Backstage. Each service, library, API is described by a catalog-info.yaml file in the repository root:
---
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: orders-api
description: REST API for order management
annotations:
gitlab.com/project-slug: backend/orders-api
backstage.io/techdocs-ref: dir:.
prometheus.io/rule: >-
sum(rate(http_requests_total{job="orders-api"}[5m]))
pagerduty.com/service-id: P12345
tags:
- go
- api
- orders-domain
spec:
type: service
lifecycle: production
owner: group:backend-team
system: orders-platform
dependsOn:
- component:postgres-orders
- component:redis-cache
providesApis:
- orders-api-v2
---
Backstage scans repositories via integrations (GitLab, GitHub, Bitbucket) and automatically adds components to the catalog. The dependsOn and providesApis relationships build a dependency graph — you can see which services depend on a Postgres cluster before planned maintenance.
The prometheus.io/rule annotation pulls metrics directly into the service card. Click on the service — you see RPS, error rate, latency for the last 24 hours without switching to Grafana.
TechDocs: Documentation Next to Code
TechDocs renders MkDocs documentation from the repository into Backstage. docs/ in the repository root + mkdocs.yml — and documentation automatically appears in the portal and updates on every push.
TechDocs configuration in app-config.yaml:
---
techdocs:
builder: external
generator:
runIn: docker
publisher:
type: googleGcs
googleGcs:
bucketName: company-techdocs
credentials: $env: GOOGLE_APPLICATION_CREDENTIALS
---builder: external — documentation generation happens in CI, not in Backstage. In GitLab CI, add a job:
---
techdocs-publish:
stage: publish
image: spotify/techdocs
script:
- techdocs-cli generate --source-dir . --output-dir ./site
- techdocs-cli publish --publisher-type googleGcs --storage-name company-techdocs --entity default/component/orders-api
only:
- main
---This way, documentation for thousands of services is generated in parallel in CI, not serially on the Backstage server. This reduces publication time from hours to minutes.
Software Templates: Scaffolding Through a Web Interface
Software Templates are a mechanism for creating new projects from templates directly through the Backstage UI. A developer fills out a form, Backstage creates a repository with the required structure, registers the component in the catalog, and configures the pipeline.
---
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: go-grpc-service
title: Go gRPC Microservice
tags: [go, grpc, recommended]
spec:
parameters:
- title: Service Configuration
required: [name, owner, system]
properties:
name:
type: string
pattern: "^[a-z][a-z0-9-]*$"
owner:
type: string
ui:field: OwnerPicker
ui:options:
allowedKinds: [Group]
system:
type: string
ui:field: EntityPicker
ui:options:
catalogFilter:
kind: System
steps:
- id: fetch
name: Fetch Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
- id: create-repo
name: Create Repository
action: publish:gitlab
input:
repoUrl: gitlab.company.com?repo=${{ parameters.name }}&owner=backend
defaultBranch: main
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
---
After the template executes, the service is immediately visible in the catalog with owner, system, and dependencies. The entire process takes less than 5 minutes.
How We Deploy Backstage on Kubernetes
Backstage on Kubernetes is a separate Deployment with PostgreSQL (for the catalog) and configuration via app-config.yaml and app-config.production.yaml. An important point: app-config.yaml is included in the image during build. Secrets — via environment variables or Vault Agent Injector. In app-config.yaml, we reference env variables:
---
integrations:
gitlab:
- host: gitlab.company.com
token: ${GITLAB_TOKEN}
kubernetes:
serviceLocatorMethod:
type: multiTenant
clusterLocatorMethods:
- type: config
clusters:
- name: production
url: https://k8s.company.com
serviceAccountToken: ${K8S_TOKEN}
caData: ${K8S_CA}
RBAC in recent Backstage versions — built-in permission system via permission policies. Before that, all authenticated users saw everything. For infrastructure with sensitive data, we must configure roles and groups.
What's Included
When ordering a turnkey Backstage setup, we:
- Analyze the infrastructure: list of services, CI/CD monitoring, authentication systems.
- Design the portal architecture: plugin selection, catalog configuration, integrations.
- Deploy Backstage on Kubernetes or Docker Compose, configure PostgreSQL.
- Write catalog-info.yaml for all services (or configure auto-discovery).
- Connect TechDocs and templates for your patterns.
- Hand over documentation, access, and conduct team training.
- Provide support for the first 2 weeks after launch.
What Really Takes Time
Deploying Backstage — one day. Making it a useful portal — several weeks. Time goes into:
- Writing catalog-info.yaml for existing services (or setting up auto-discovery with filtering rules)
- Connecting existing tools: Prometheus, PagerDuty, Argo CD, Vault, Jira
- Creating Software Templates for actual team patterns
- Setting up TechDocs and populating initial documentation
- Training the team
The Backstage plugin ecosystem is both a strength and a weakness. There are plugins for almost any tool, but quality varies: some are actively maintained, others abandoned on old versions and break on update. Before choosing a plugin, we check the last commit date and open issues. We guarantee stability: we use only proven plugins and keep them current.
Comparison of implementation time for different components
| Component | Implementation Time |
|---|---|
| Basic catalog | 2–3 days |
| TechDocs | 3–5 days |
| Software Templates (5 templates) | 5–7 days |
| Prometheus integration | 1–2 days |
| RBAC | 2–3 days |
Timelines
Basic Backstage with catalog for existing services, TechDocs, and a few Software Templates — 2–4 weeks. Full integration with all tools, permission policies, custom plugins — 1–3 months. Cost is calculated individually after infrastructure audit and scope discussion. Contact us for a consultation — we'll assess your project and offer the optimal solution. We guarantee the portal will be useful to the team from day one.
According to GitHub data, the Backstage project has over 700 contributors and 25,000 stars.







