ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Internal Developer Portals

Build an internal developer portal that brings together service catalogs, documentation, CI/CD status, and team ownership into a single pane of glass. Covers Backstage architecture, plugin ecosystem, entity modeling, and adoption strategies.

As engineering organizations grow, developers spend increasing time searching: “Who owns this service?” “Where is the API documentation?” “What is the deployment status?” An internal developer portal centralizes all of this information, reducing cognitive load and eliminating the treasure hunt across wikis, dashboards, and Slack channels.


Why Developer Portals

Without a portal:
  Find service owner → Search Slack, ask around (15 min)
  Read API docs → Search wiki, maybe outdated (10 min)
  Check deployment status → Open CI/CD tool (5 min)
  Find runbook → Search Confluence, maybe not indexed (10 min)
  Total context-switching: 40 minutes per unfamiliar service

With a portal:
  Open portal → Search service → All info in one page (2 min)

Backstage Architecture

Spotify’s Backstage is the leading open-source developer portal framework:

                    ┌─────────────────────────────┐
                    │     Backstage Frontend       │
                    │  (React, Plugin-based UI)    │
                    └──────────────┬──────────────┘

                    ┌──────────────┴──────────────┐
                    │     Backstage Backend        │
                    │  (Node.js, Plugin APIs)      │
                    └──────────────┬──────────────┘

              ┌────────────────────┼────────────────────┐
              │                    │                    │
       Software Catalog     Tech Docs Engine     Plugin APIs
       (entities, APIs)     (MkDocs, TechDocs)   (CI/CD, Cloud)

Entity Model

# catalog-info.yaml (lives in each service's repo)
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: order-service
  description: "Handles order lifecycle management"
  annotations:
    github.com/project-slug: "org/order-service"
    pagerduty.com/service-id: "P1234567"
    grafana.com/dashboard-id: "d/order-service"
  tags:
    - java
    - spring-boot
    - tier-1
spec:
  type: service
  lifecycle: production
  owner: order-team
  system: commerce-platform
  providesApis:
    - order-api
  consumesApis:
    - payment-api
    - inventory-api
  dependsOn:
    - resource:order-database

Core Features

Software Catalog

The service catalog is the spine of the portal:

Service: order-service
Owner: Order Team (@order-team)
Lifecycle: Production
System: Commerce Platform

Links:
  - GitHub: github.com/org/order-service
  - CI/CD: github.com/org/order-service/actions
  - Dashboard: grafana.internal/d/order-service
  - Runbook: wiki.internal/runbooks/order-service
  - PagerDuty: pagerduty.com/services/P1234567
  - API Docs: portal.internal/api/order-api

Dependencies:
  Provides: order-api (OpenAPI v3)
  Consumes: payment-api, inventory-api
  Database: order-database (PostgreSQL)

TechDocs

Documentation generated from markdown in each service’s repository:

docs/
├── index.md           → Overview
├── architecture.md    → System design
├── api-reference.md   → API documentation
├── runbooks/
│   ├── troubleshooting.md
│   └── deployment.md
└── adr/
    ├── 001-choose-postgresql.md
    └── 002-event-driven-arch.md

Templates (Scaffolder)

Create new services from templates:

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: spring-boot-service
  title: Spring Boot Microservice
spec:
  parameters:
    - title: Service Details
      properties:
        name:
          type: string
          title: Service Name
        owner:
          type: string
          title: Owner Team
        description:
          type: string
          title: Description
  steps:
    - id: create-repo
      action: github:repo:create
    - id: scaffold
      action: fetch:template
      input:
        url: ./skeleton
    - id: register
      action: catalog:register

Adoption Strategy

Phase 1: Catalog (Month 1-2)
  - Register 20 most critical services
  - Define ownership for all registered services
  - Link to existing dashboards and docs

Phase 2: Documentation (Month 3-4)
  - Enable TechDocs for all registered services
  - Migrate runbooks to service repos
  - Create API documentation standards

Phase 3: Templates (Month 5-6)
  - Create templates for common service types
  - Golden path: new service ready in < 30 minutes
  - Link to CI/CD, monitoring, alerting setup

Phase 4: Plugins (Month 7+)
  - CI/CD status in portal
  - Cloud cost per service
  - Dependency graph visualization
  - Security scan results

Anti-Patterns

Anti-PatternConsequenceFix
Portal with stale dataDevelopers stop using itAutomate data sourcing from repos
Mandatory ALL informationAdoption bottleneckStart minimal, grow iteratively
No team ownership”Commons” nobody maintainsEvery service has an owner
Portal as documentation dumpInformation overloadCurate, prioritize discoverability
Building from scratchReinventing the wheelUse Backstage or Port.io

A developer portal succeeds when developers choose to use it because it is the fastest way to find information — not because they are told to.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →