Platform Engineering: Building Internal Developer Platforms That Actually Get Used
on Platform engineering, Devops, Idp, Kubernetes, Backstage, Developer experience
Platform Engineering: Building Internal Developer Platforms That Actually Get Used
Most Internal Developer Platforms (IDPs) die quietly. They’re built with good intentions, launched with fanfare, and abandoned within a year. Not because the idea was bad — but because teams built a product nobody wanted to buy.
This post breaks down what separates successful IDPs from expensive shelfware.
Photo by Growtika on Unsplash
The Core Problem: Platforms as a Product
Platform teams often think they’re building infrastructure. They’re not. They’re building a product whose customers are internal developers. And product success requires:
- Understanding the customer (what does a dev actually struggle with?)
- Reducing friction (not adding it with mandatory tickets and approvals)
- Measuring adoption (not “we deployed it” but “devs actually use it”)
The most common failure mode: a platform team builds what they think developers need, based on their own infrastructure perspective — not what developers actually find painful.
The Golden Path Framework
The “golden path” concept, popularized by Spotify’s engineering culture, is the right mental model:
A golden path is an opinionated, well-lit path that gets you from “I have an idea” to “it’s running in production” with minimal friction. It’s not a mandatory railroad. It’s a recommendation that’s easy enough to follow that most people choose it voluntarily.
What a Golden Path Includes
┌─────────────────────────────────────────────────────────────────┐
│ Golden Path │
│ │
│ Code Template ──► CI Pipeline ──► Container Build ──► Deploy │
│ │ │ │ │ │
│ (scaffolding) (testing, (scanning, (canary, │
│ linting, signing, rollback) │
│ SAST) SBOM) │
│ │
│ All preconfigured. One command to start. Zero config to deploy. │
└─────────────────────────────────────────────────────────────────┘
Architecture: The Modern IDP Stack
A practical IDP in 2026 typically combines:
1. Developer Portal — Backstage (or Alternatives)
Backstage remains the dominant open-source portal, though commercial alternatives (Port, Cortex, OpsLevel) have matured significantly.
# backstage/catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payments-service
description: Core payment processing service
annotations:
github.com/project-slug: myorg/payments-service
grafana/dashboard-selector: "payments"
pagerduty.com/service-id: "PXXXXXX"
sonarqube.org/project-key: "payments-service"
tags:
- java
- payments
- tier-1
spec:
type: service
lifecycle: production
owner: group:payments-team
system: financial-platform
dependsOn:
- component:user-service
- resource:payments-database
providesApis:
- payments-api-v3
This single YAML file, committed alongside the code, automatically:
- Registers the service in the software catalog
- Links to dashboards, alerts, and on-call
- Tracks dependencies
- Shows code quality metrics
2. Self-Service with Crossplane
Crossplane lets you expose Kubernetes-native APIs for cloud resources:
# A developer "orders" a database by applying this YAML
apiVersion: database.platform.company.com/v1alpha1
kind: PostgresInstance
metadata:
name: my-service-db
namespace: my-team
spec:
parameters:
storageGB: 20
tier: standard # Defined by platform team: maps to RDS db.t3.medium
backupEnabled: true
maintenanceWindow: "Sun:03:00-Sun:04:00"
writeConnectionSecretToRef:
name: my-service-db-credentials
The platform team defines what “standard tier” means (instance type, multi-AZ, backup policy). The developer just declares their intent. No tickets. No waiting.
3. Scaffolding with Backstage Software Templates
# backstage/templates/microservice/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: microservice-java
title: Java Microservice
description: Create a production-ready Spring Boot microservice
tags: [java, microservice, recommended]
spec:
owner: platform-team
type: service
parameters:
- title: Service Details
required: [name, description, owner]
properties:
name:
title: Service Name
type: string
pattern: '^[a-z][a-z0-9-]*$'
javaVersion:
title: Java Version
type: string
default: "21"
enum: ["21", "17"]
includeDatabase:
title: Include PostgreSQL?
type: boolean
default: false
steps:
- id: fetch
name: Fetch Template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
javaVersion: ${{ parameters.javaVersion }}
- id: create-repo
name: Create GitHub Repository
action: github:repo:create
input:
repoUrl: github.com?owner=myorg&repo=${{ parameters.name }}
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }}
A developer fills in a form in the UI, clicks “Create,” and gets:
- A new GitHub repository with standard structure
- Pre-configured CI/CD pipeline
- Grafana dashboard
- Runbook template
- Automatic catalog registration
Time from “I need a new service” to “first deployment”: under 5 minutes.
The Platform API Surface
Define your platform API carefully. The right level of abstraction:
# Too low-level (forcing devs to know k8s internals):
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
# ... 40 more lines of config
# Just right (developer expresses intent, platform handles details):
apiVersion: apps.platform.company.com/v1
kind: WebService
metadata:
name: my-service
spec:
image: myorg/my-service:v1.2.3
tier: standard # Platform maps this to appropriate k8s resources
replicas: 2
healthCheckPath: /healthz
env:
- name: DATABASE_URL
valueFrom:
secretRef: my-service-db-credentials
Measuring Platform Success
Don’t measure:
- “Number of services onboarded” (vanity metric)
- “Platform uptime” (baseline expectation, not success)
Do measure:
Developer Experience Metrics:
├── DORA Metrics (deployment frequency, lead time, MTTR, CFR)
├── Self-service rate: % of infra provisioned without tickets
├── Time-to-first-deployment: new service → prod in minutes
├── Platform NPS: quarterly survey of developer satisfaction
└── Cognitive load: survey "how much do you need to know about infra to deploy?"
Adoption Metrics:
├── Weekly active users of the developer portal
├── % of services using golden path templates
├── % of deployments using platform CI/CD
└── Support ticket reduction rate
Common Anti-Patterns to Avoid
1. The Mandatory Tax
Making the platform mandatory before it’s better than the alternative. Developers will route around you if you force them into something that slows them down.
Fix: Make the golden path so good that developers choose it. Mandate it only when it’s clearly better.
2. The Feature Factory
Building features based on platform team assumptions instead of developer requests.
Fix: Embed platform engineers in product teams for 1-2 months per year. You’ll learn more about actual pain than any survey.
3. The Abstraction Ceiling
Building abstractions that work for 90% of cases but make the 10% edge cases impossible.
Fix: Always provide an “escape hatch” to the raw underlying platform. The golden path should be the easy path, not the only path.
4. The Documentation Debt
Building great tools with no documentation.
Fix: Treat docs as a first-class deliverable. A feature that isn’t documented doesn’t exist.
Getting Started: A 90-Day Roadmap
Days 1-30: Listen and Learn
- Interview 15+ developers across teams
- Map their current deployment journey
- Identify the top 3 pain points
- Define success metrics
Days 31-60: Build the MVP
- Implement ONE golden path end-to-end
- Launch Backstage (or chosen portal) with basic catalog
- Set up self-service for the #1 pain point
Days 61-90: Iterate and Measure
- Measure adoption
- Run NPS survey
- Fix the sharp edges
- Document everything
Key Takeaways
- Platform engineering is product engineering — treat developers as customers
- Golden paths work because they’re easy to choose, not mandatory
- Self-service (Crossplane, Backstage templates) eliminates ticket-driven bottlenecks
- Measure developer experience metrics, not infrastructure metrics
- Avoid over-engineering abstractions — always provide escape hatches
The best IDP is the one developers actually use. Build for them, not for your architecture diagrams.
Photo by Annie Spratt on Unsplash
이 글이 도움이 되셨다면 공감 및 광고 클릭을 부탁드립니다 :)
