Linking Runbooks to Services in the Catalog

A runbook nobody can find during an incident is a runbook that does not exist. The fix is structural: attach the runbook to the service in the catalog so it is one click from the entity page the responder is already looking at. This how-to links runbooks to services via annotations, keeps them close to the code, and surfaces them on the entity overview. It is the link-out half of Incident & On-Call Workflows within Developer Experience & Self-Service Platforms.

Prerequisites

  • Backstage 1.20+ with the catalog populated and services owned correctly.
  • Runbooks authored as durable content — ideally TechDocs pages beside the service, per TechDocs & Documentation Pipelines, so they version with the code.
  • Agreement on what a runbook must contain: symptoms, first checks, mitigation, and escalation.
  • Write access to each service’s catalog-info.yaml to add link annotations.
Prerequisites for linking runbooks A populated catalog, runbooks as content, an agreed runbook shape, and write access enable linking. populated catalog runbooks as content agreed runbook shape write to catalog-info One click away from the entity
Authoring runbooks as TechDocs beside the code means they version with the service and cannot rot in a forgotten wiki.

Exact Configuration

  1. Add link annotations to the service so the runbook appears in the entity’s Links.

    # catalog-info.yaml
    apiVersion: backstage.io/v1alpha1
    kind: Component
    metadata:
      name: payments
      links:
        - url: https://backstage.example.com/docs/default/component/payments/runbooks/high-latency
          title: Runbook — High Latency
          icon: docs
    spec:
      type: service
      owner: team-payments
    
  2. Keep runbooks in the service’s TechDocs so the link resolves to versioned content, not an external wiki page.

    <!-- docs/runbooks/high-latency.md -->
    # Runbook: High Latency
    
    ## Symptoms
    p99 latency above 500ms for 5 minutes.
    
    ## First checks
    1. Is an incident already open? Check the entity overview.
    2. Recent deploy? Compare against the deploy timeline.
    
    ## Mitigation
    Roll back the last deploy; scale the read replicas.
    
    ## Escalation
    If unresolved in 15 minutes, page the on-call lead.
    
  3. Register the docs in mkdocs.yml so the runbook is built and reachable.

    # mkdocs.yml
    nav:
      - Runbooks:
          - High Latency: runbooks/high-latency.md
    
Runbook linked from the entity A link annotation on the service points at a versioned TechDocs runbook, surfaced in the entity's Links. link annotation catalog-info.yaml TechDocs runbook versioned content entity Links one click in an incident
Because the link points at TechDocs rather than a wiki URL, the runbook a responder opens is always the one matching the deployed code.

Validation

# Requires curl, jq
# 1. The service entity carries a runbook link
curl -s "${PORTAL_URL}/api/catalog/entities/by-name/component/default/payments" \
  | jq '[.metadata.links[] | select(.title | test("Runbook"))] | length'
# Expected: >= 1

# 2. The linked runbook page actually resolves
curl -s -o /dev/null -w "%{http_code}\n" \
  "${PORTAL_URL}/docs/default/component/payments/runbooks/high-latency/"
# Expected: 200

# 3. No service is missing a runbook link (governance sweep)
curl -s "${PORTAL_URL}/api/catalog/entities?filter=kind=component" \
  | jq '[.[] | select(([.metadata.links // [] | .[].title] | any(test("Runbook"))) | not) | .metadata.name]'
# Expected: [] once every service has one
Runbook link validation checks The entity carries a link, the linked page resolves, and no service is missing a runbook. Link present on the entity Page resolves 200, not 404 None missing coverage sweep
The coverage sweep turns "we should have runbooks" into an enforceable list of services that still lack one.

Edge Cases & Troubleshooting

Symptom Root Cause Resolution
Runbook link 404s Docs not built or path changed Rebuild TechDocs; confirm the nav path matches the link
Link points at a stale wiki Runbook lives outside version control Move it into the service’s TechDocs so it versions with code
No runbook on a critical service No coverage enforcement Run the sweep in CI and fail on services missing a link
Responder opens the wrong runbook Generic title, unclear scope Title runbooks by symptom, e.g. “High Latency”, not “Runbook”
Runbook steps are out of date Never exercised Reference it in incident reviews so gaps get fixed
Runbook-linking pitfalls by class Broken links and stale wikis are freshness issues; missing coverage and unclear scope are governance issues. Freshness link 404s stale wiki → TechDocs + rebuild Governance no coverage unclear scope → sweep + symptom titles
Enforcing coverage in CI is what keeps runbook links from being an aspiration that decays the moment attention moves on.

Frequently Asked Questions

One runbook per service, or one per failure mode?

Per failure mode, titled by symptom. A responder arrives with a symptom — high latency, elevated errors, a failing dependency — and wants the matching playbook, not a wall of prose covering everything. Several short, well-titled runbooks beat one exhaustive document nobody reads under pressure.

Should runbooks live in the portal or in the paging tool?

Author them once in TechDocs beside the code so they version with the service, then link to them from wherever a responder starts — the entity page and, if your paging tool supports it, the alert itself. A single source of truth linked from many places avoids the drift you get when the same runbook is pasted into two systems.