Platform Engineering
Best practices for building Internal Developer Platforms (IDPs) that reduce cognitive load, accelerate delivery, and create golden paths for development teams.
IDP Architecture Layers
A well-designed IDP separates concerns into distinct layers. Each layer abstracts complexity from the one above it.
Developer Interface (Portal / CLI / API)
|
Orchestration Layer (Workflows, Templates, Scaffolding)
|
Integration Layer (APIs, Plugins, Connectors)
|
Resource Layer (Infrastructure, Services, Tools)
| Layer |
Purpose |
Components |
Owned By |
| Developer Interface |
Self-service entry point |
Backstage portal, CLI tools, API gateway |
Platform team |
| Orchestration |
Workflow automation, templating |
Scaffolder, Terraform modules, Crossplane |
Platform team |
| Integration |
Connect tools and services |
Backstage plugins, API adapters, webhooks |
Platform + tool owners |
| Resource |
Actual infrastructure and services |
Kubernetes, databases, CI/CD, monitoring |
Infrastructure team |
| Governance |
Policy enforcement and compliance |
OPA, Kyverno, cost policies, security scans |
Security + platform team |
Platform Team Topology and Responsibilities
Team Structure
| Role |
Responsibility |
Focus Area |
| Platform Product Manager |
Roadmap, prioritization, user research |
Developer needs, adoption metrics |
| Platform Engineer |
IDP core, golden paths, automation |
Infrastructure abstraction, tooling |
| Developer Advocate |
Documentation, onboarding, feedback loops |
DevEx, training, communication |
| SRE/Reliability Lead |
Platform reliability, SLOs, incident response |
Uptime, performance, observability |
| Security Engineer |
Policy-as-code, compliance automation |
Guardrails, scanning, access control |
Interaction Model
Stream-Aligned Teams (consumers)
|
| self-service requests
v
Platform Team (enablers)
|
| golden paths, templates, APIs
v
Infrastructure / Cloud (resources)
Platform teams operate as enabling teams (Team Topologies model). They reduce cognitive load on stream-aligned teams by providing curated, opinionated abstractions.
Backstage: Service Catalog and Developer Portal
catalog-info.yaml -- Service Registration
Every service registers itself in the catalog via a catalog-info.yaml at the repo root.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Handles payment processing and refunds
annotations:
github.com/project-slug: acme-corp/payment-service
backstage.io/techdocs-ref: dir:.
pagerduty.com/service-id: P1234ABC
grafana/dashboard-selector: "payment-service"
tags:
- java
- spring-boot
- payments
links:
- url: https://grafana.internal/d/payments
title: Dashboard
icon: dashboard
- url: https://runbooks.internal/payments
title: Runbook
icon: docs
spec:
type: service
lifecycle: production
owner: team-payments
system: checkout-system
providesApis:
- payment-api
consumesApis:
- inventory-api
- notification-api
dependsOn:
- resource:payments-db
- component:auth-service
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: payment-api
description: Payment processing REST API
spec:
type: openapi
lifecycle: production
owner: team-payments
system: checkout-system
definition:
$text: ./openapi.yaml
Service Catalog API -- Querying Components
# List all components owned by a team
curl -s "https://backstage.internal/api/catalog/entities?filter=kind=component,spec.owner=team-payments" \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '.[] | {name: .metadata.name, lifecycle: .spec.lifecycle}'
# Find all services consuming a specific API
curl -s "https://backstage.internal/api/catalog/entities?filter=kind=component,spec.consumesApis=payment-api" \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '.[] | .metadata.name'
# Get component details with relations
curl -s "https://backstage.internal/api/catalog/entities/by-name/component/default/payment-service" \
-H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '{
name: .metadata.name,
owner: .spec.owner,
apis: .spec.providesApis,
dependencies: .spec.dependsOn
}'
Golden Path Templates
Golden paths are opinionated, pre-configured templates that encode best practices. They give teams a paved road to production.
Backstage Software Template
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: spring-boot-service
title: Spring Boot Microservice
description: Creates a production-ready Spring Boot service with CI/CD, monitoring, and database
tags:
- java
- spring-boot
- recommended
spec:
owner: platform-team
type: service
parameters:
- title: Service Details
required:
- name
- owner
- description
properties:
name:
title: Service Name
type: string
pattern: '^[a-z][a-z0-9-]*$'
ui:autofocus: true
owner:
title: Owner Team
type: string
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: Group
description:
title: Description
type: string
javaVersion:
title: Java Version
type: string
default: '21'
enum: ['17', '21']
- title: Infrastructure
properties:
database:
title: Database
type: string
default: postgresql
enum: [postgresql, mysql, none]
cacheLayer:
title: Cache Layer
type: string
default: none
enum: [redis, none]
messageBroker:
title: Message Broker
type: string
default: none
enum: [kafka, rabbitmq, none]
steps:
- id: fetch-template
name: Fetch Skeleton
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
description: ${{ parameters.description }}
javaVersion: ${{ parameters.javaVersion }}
database: ${{ parameters.database }}
- id: create-repo
name: Create Repository
action: publish:github
input:
repoUrl: github.com?owner=acme-corp&repo=${{ parameters.name }}
description: ${{ parameters.description }}
defaultBranch: main
protectDefaultBranch: true
requireCodeOwnerReviews: true
- id: register-catalog
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
- id: create-argocd-app
name: Create ArgoCD Application
action: argocd:create-resources
input:
appName: ${{ parameters.name }}
repoUrl: ${{ steps['create-repo'].output.remoteUrl }}
output:
links:
- title: Repository
url: ${{ steps['create-repo'].output.remoteUrl }}
- title: Service in Catalog
url: ${{ steps['register-catalog'].output.entityRef }}
- title: CI/CD Pipeline
url: ${{ steps['create-repo'].output.remoteUrl }}/actions
Golden Path Coverage Matrix
| Category |
What the Golden Path Provides |
Without Golden Path |
| Repository |
Pre-configured with CI/CD, linting, CODEOWNERS |
Manual setup, inconsistent configs |
| CI/CD |
Working pipeline from day one |
Copy-paste from other repos, broken configs |
| Observability |
Dashboards, alerts, SLOs pre-configured |
No monitoring until first incident |
| Security |
Dependency scanning, SAST, secrets detection |
Added retroactively (if at all) |
| Documentation |
ADR template, README structure, API docs |
Empty README, no docs |
| Infrastructure |
Terraform modules, Kubernetes manifests |
Hand-crafted YAML, drift between envs |
| Testing |
Test framework, coverage gates, fixtures |
Ad-hoc test setup, no coverage requirements |
Developer Experience Metrics (SPACE Framework)
Measure platform effectiveness using the SPACE framework. Never rely on a single dimension.
| Dimension |
What It Measures |
Example Metrics |
Collection Method |
| Satisfaction |
How developers feel about the platform |
NPS score, satisfaction survey (1-5) |
Quarterly survey |
| Performance |
Outcome of developer work |
Deployment frequency, change failure rate |
DORA metrics pipeline |
| Activity |
Volume of actions |
Scaffolding requests, API calls, portal visits |
Platform telemetry |
| Communication |
Quality of collaboration |
Time to first response on platform support |
Ticketing system |
| Efficiency |
Flow and minimal friction |
Time from commit to deploy, onboarding time |
Pipeline metrics |
Key DevEx Metrics Dashboard
# Platform DevEx Metrics -- collected via platform telemetry
metrics:
onboarding:
time_to_first_deploy:
target: "< 2 hours"
description: "Time from new hire to first successful deployment"
source: "scaffolder + pipeline timestamps"
time_to_first_commit:
target: "< 4 hours"
description: "Time from repo creation to first merged commit"
source: "github events"
self_service:
template_adoption_rate:
target: "> 80%"
description: "Percentage of new services using golden path templates"
source: "backstage scaffolder logs"
self_service_resolution_rate:
target: "> 70%"
description: "Percentage of requests resolved without platform team intervention"
source: "support tickets vs portal actions"
reliability:
platform_availability:
target: "99.9%"
description: "Uptime of developer portal, CI/CD, and artifact registry"
source: "synthetic monitoring"
mean_time_to_recovery:
target: "< 30 minutes"
description: "Time to restore platform services after incident"
source: "incident management system"
delivery:
deployment_frequency:
target: "multiple per day per team"
description: "How often teams deploy to production"
source: "deployment pipeline events"
lead_time_for_changes:
target: "< 1 day"
description: "Time from commit to production"
source: "git + pipeline timestamps"
Self-Service Portal Workflow
Request Flow Architecture
Developer submits request via Portal UI
|
v
Request Validation (schema check, policy check)
|
v
Approval Gate (if required by policy)
| |
| auto | manual
v v
Orchestration Engine (executes workflow)
|
+---> Provision Infrastructure (Terraform/Crossplane)
+---> Configure CI/CD (GitHub Actions / ArgoCD)
+---> Register in Catalog (Backstage)
+---> Set Up Monitoring (Grafana / PagerDuty)
+---> Notify Team (Slack / Email)
|
v
Verification (health checks, smoke tests)
|
v
Developer notified -- ready to use
Self-Service Capability Matrix
| Capability |
Automation Level |
Approval Required |
Typical Time |
| Create new service |
Fully automated |
No |
5 minutes |
| Provision database |
Fully automated |
No (dev/staging), Yes (prod) |
10 minutes |
| Add CI/CD pipeline |
Fully automated |
No |
2 minutes |
| Request cloud credentials |
Semi-automated |
Yes (security review) |
1 hour |
| Create new environment |
Fully automated |
No (non-prod), Yes (prod) |
15 minutes |
| Add monitoring/alerts |
Fully automated |
No |
5 minutes |
| Resize infrastructure |
Semi-automated |
Yes (cost review > threshold) |
30 minutes |
| Decommission service |
Automated with safeguards |
Yes (owner confirmation) |
10 minutes |
Platform Engineering Maturity Model
| Level |
Name |
Characteristics |
Capabilities |
| 0 |
Ad Hoc |
No platform, tribal knowledge |
Teams manage their own infra |
| 1 |
Reactive |
Shared scripts, wiki docs |
Basic CI/CD, manual provisioning |
| 2 |
Standardized |
Golden paths, basic portal |
Service templates, catalog, basic self-service |
| 3 |
Optimized |
Full IDP, metrics-driven |
Self-service everything, DevEx metrics, policy-as-code |
| 4 |
Strategic |
Platform as product, innovation |
API-first platform, marketplace, continuous feedback |
Maturity Assessment Checklist
Level 1 --> Level 2:
[x] Service catalog exists and is maintained
[x] At least 3 golden path templates available
[x] Basic developer portal deployed
[x] CI/CD standardized across teams
Level 2 --> Level 3:
[x] Self-service for >80% of common requests
[x] SPACE metrics collected and reviewed monthly
[x] Policy-as-code enforced (not advisory)
[x] Platform team has dedicated product manager
[x] Internal SLOs defined for platform services
Level 3 --> Level 4:
[x] API-first platform (all capabilities programmable)
[x] Internal developer marketplace for plugins/extensions
[x] Continuous developer experience research program
[x] Platform economics model (cost attribution per team)
[x] Platform contributes to organizational strategy
Anti-Patterns
| Anti-Pattern |
Problem |
Fix |
| Build it and they will come |
No adoption without developer input |
Treat platform as product; user research before building |
| Ticket-ops disguised as platform |
Self-service portal that just creates tickets |
Automate end-to-end; tickets are a smell, not a solution |
| Mandating platform use |
Forced adoption breeds resentment and workarounds |
Make the golden path the easiest path, not the only path |
| One-size-fits-all templates |
Overly rigid templates that don't fit team needs |
Composable templates with sensible defaults and escape hatches |
| No feedback loops |
Platform team builds in isolation |
Regular surveys, office hours, embedded rotations with teams |
| Ignoring developer experience |
Technically correct but painful to use |
Measure DevEx metrics, optimize for developer happiness |
| Platform team as bottleneck |
All changes go through platform team |
Self-service with guardrails; teams should not wait on platform |
| Over-abstracting too early |
Complex abstraction layers before understanding needs |
Start with concrete solutions, abstract when patterns emerge |
| Neglecting documentation |
Powerful platform nobody knows how to use |
Docs-as-code, TechDocs in Backstage, examples for everything |
| No platform SLOs |
Platform reliability treated as best-effort |
Define and publish SLOs; platform is a product with SLAs |
| Shadow platforms |
Teams build their own tooling around the platform |
Understand why and address gaps; shadow platforms reveal unmet needs |
| Gold plating the portal |
Spending months on portal UI before delivering value |
Ship incrementally; a working CLI beats a beautiful but empty portal |
Platform Engineering Checklist
1---2name: platform-engineering-23description: Provides platform engineering best practices for Internal Developer Platforms (IDPs), golden paths, service catalogs, and developer experience. Use when building developer platforms, configuring Backstage, designing self-service workflows, or when user mentions 'platform engineering', 'backstage', 'golden path', 'IDP', 'developer portal', 'service catalog', 'DevEx', 'platform team', 'self-service'.4---5# Platform Engineering
6
7Best practices for building Internal Developer Platforms (IDPs) that reduce cognitive load, accelerate delivery, and create golden paths for development teams.
8
9## IDP Architecture Layers
10
11A well-designed IDP separates concerns into distinct layers. Each layer abstracts complexity from the one above it.
12
13```
14Developer Interface (Portal / CLI / API)
15 |
16 Orchestration Layer (Workflows, Templates, Scaffolding)
17 |
18 Integration Layer (APIs, Plugins, Connectors)
19 |
20 Resource Layer (Infrastructure, Services, Tools)
21```
22
23| Layer | Purpose | Components | Owned By |
24|-------|---------|------------|----------|
25| Developer Interface | Self-service entry point | Backstage portal, CLI tools, API gateway | Platform team |
26| Orchestration | Workflow automation, templating | Scaffolder, Terraform modules, Crossplane | Platform team |
27| Integration | Connect tools and services | Backstage plugins, API adapters, webhooks | Platform + tool owners |
28| Resource | Actual infrastructure and services | Kubernetes, databases, CI/CD, monitoring | Infrastructure team |
29| Governance | Policy enforcement and compliance | OPA, Kyverno, cost policies, security scans | Security + platform team |
30
31## Platform Team Topology and Responsibilities
32
33### Team Structure
34
35| Role | Responsibility | Focus Area |
36|------|---------------|------------|
37| Platform Product Manager | Roadmap, prioritization, user research | Developer needs, adoption metrics |
38| Platform Engineer | IDP core, golden paths, automation | Infrastructure abstraction, tooling |
39| Developer Advocate | Documentation, onboarding, feedback loops | DevEx, training, communication |
40| SRE/Reliability Lead | Platform reliability, SLOs, incident response | Uptime, performance, observability |
41| Security Engineer | Policy-as-code, compliance automation | Guardrails, scanning, access control |
42
43### Interaction Model
44
45```
46Stream-Aligned Teams (consumers)
47 |
48 | self-service requests
49 v
50Platform Team (enablers)
51 |
52 | golden paths, templates, APIs
53 v
54Infrastructure / Cloud (resources)
55```
56
57Platform teams operate as **enabling teams** (Team Topologies model). They reduce cognitive load on stream-aligned teams by providing curated, opinionated abstractions.
58
59## Backstage: Service Catalog and Developer Portal
60
61### catalog-info.yaml -- Service Registration
62
63Every service registers itself in the catalog via a `catalog-info.yaml` at the repo root.
64
65```yaml
66apiVersion: backstage.io/v1alpha1
67kind: Component
68metadata:
69 name: payment-service
70 description: Handles payment processing and refunds
71 annotations:
72 github.com/project-slug: acme-corp/payment-service
73 backstage.io/techdocs-ref: dir:.
74 pagerduty.com/service-id: P1234ABC
75 grafana/dashboard-selector: "payment-service"
76 tags:
77 - java
78 - spring-boot
79 - payments
80 links:
81 - url: https://grafana.internal/d/payments
82 title: Dashboard
83 icon: dashboard
84 - url: https://runbooks.internal/payments
85 title: Runbook
86 icon: docs
87spec:
88 type: service
89 lifecycle: production
90 owner: team-payments
91 system: checkout-system
92 providesApis:
93 - payment-api
94 consumesApis:
95 - inventory-api
96 - notification-api
97 dependsOn:
98 - resource:payments-db
99 - component:auth-service
100
101---
102apiVersion: backstage.io/v1alpha1
103kind: API
104metadata:
105 name: payment-api
106 description: Payment processing REST API
107spec:
108 type: openapi
109 lifecycle: production
110 owner: team-payments
111 system: checkout-system
112 definition:
113 $text: ./openapi.yaml
114```
115
116### Service Catalog API -- Querying Components
117
118```bash
119# List all components owned by a team
120curl -s "https://backstage.internal/api/catalog/entities?filter=kind=component,spec.owner=team-payments" \
121 -H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '.[] | {name: .metadata.name, lifecycle: .spec.lifecycle}'
122
123# Find all services consuming a specific API
124curl -s "https://backstage.internal/api/catalog/entities?filter=kind=component,spec.consumesApis=payment-api" \
125 -H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '.[] | .metadata.name'
126
127# Get component details with relations
128curl -s "https://backstage.internal/api/catalog/entities/by-name/component/default/payment-service" \
129 -H "Authorization: Bearer $BACKSTAGE_TOKEN" | jq '{
130 name: .metadata.name,
131 owner: .spec.owner,
132 apis: .spec.providesApis,
133 dependencies: .spec.dependsOn
134 }'
135```
136
137## Golden Path Templates
138
139Golden paths are opinionated, pre-configured templates that encode best practices. They give teams a paved road to production.
140
141### Backstage Software Template
142
143```yaml
144apiVersion: scaffolder.backstage.io/v1beta3
145kind: Template
146metadata:
147 name: spring-boot-service
148 title: Spring Boot Microservice
149 description: Creates a production-ready Spring Boot service with CI/CD, monitoring, and database
150 tags:
151 - java
152 - spring-boot
153 - recommended
154spec:
155 owner: platform-team
156 type: service
157
158 parameters:
159 - title: Service Details
160 required:
161 - name
162 - owner
163 - description
164 properties:
165 name:
166 title: Service Name
167 type: string
168 pattern: '^[a-z][a-z0-9-]*$'
169 ui:autofocus: true
170 owner:
171 title: Owner Team
172 type: string
173 ui:field: OwnerPicker
174 ui:options:
175 catalogFilter:
176 kind: Group
177 description:
178 title: Description
179 type: string
180 javaVersion:
181 title: Java Version
182 type: string
183 default: '21'
184 enum: ['17', '21']
185
186 - title: Infrastructure
187 properties:
188 database:
189 title: Database
190 type: string
191 default: postgresql
192 enum: [postgresql, mysql, none]
193 cacheLayer:
194 title: Cache Layer
195 type: string
196 default: none
197 enum: [redis, none]
198 messageBroker:
199 title: Message Broker
200 type: string
201 default: none
202 enum: [kafka, rabbitmq, none]
203
204 steps:
205 - id: fetch-template
206 name: Fetch Skeleton
207 action: fetch:template
208 input:
209 url: ./skeleton
210 values:
211 name: ${{ parameters.name }}
212 owner: ${{ parameters.owner }}
213 description: ${{ parameters.description }}
214 javaVersion: ${{ parameters.javaVersion }}
215 database: ${{ parameters.database }}
216
217 - id: create-repo
218 name: Create Repository
219 action: publish:github
220 input:
221 repoUrl: github.com?owner=acme-corp&repo=${{ parameters.name }}
222 description: ${{ parameters.description }}
223 defaultBranch: main
224 protectDefaultBranch: true
225 requireCodeOwnerReviews: true
226
227 - id: register-catalog
228 name: Register in Catalog
229 action: catalog:register
230 input:
231 repoContentsUrl: ${{ steps['create-repo'].output.repoContentsUrl }}
232 catalogInfoPath: /catalog-info.yaml
233
234 - id: create-argocd-app
235 name: Create ArgoCD Application
236 action: argocd:create-resources
237 input:
238 appName: ${{ parameters.name }}
239 repoUrl: ${{ steps['create-repo'].output.remoteUrl }}
240
241 output:
242 links:
243 - title: Repository
244 url: ${{ steps['create-repo'].output.remoteUrl }}
245 - title: Service in Catalog
246 url: ${{ steps['register-catalog'].output.entityRef }}
247 - title: CI/CD Pipeline
248 url: ${{ steps['create-repo'].output.remoteUrl }}/actions
249```
250
251### Golden Path Coverage Matrix
252
253| Category | What the Golden Path Provides | Without Golden Path |
254|----------|------------------------------|---------------------|
255| Repository | Pre-configured with CI/CD, linting, CODEOWNERS | Manual setup, inconsistent configs |
256| CI/CD | Working pipeline from day one | Copy-paste from other repos, broken configs |
257| Observability | Dashboards, alerts, SLOs pre-configured | No monitoring until first incident |
258| Security | Dependency scanning, SAST, secrets detection | Added retroactively (if at all) |
259| Documentation | ADR template, README structure, API docs | Empty README, no docs |
260| Infrastructure | Terraform modules, Kubernetes manifests | Hand-crafted YAML, drift between envs |
261| Testing | Test framework, coverage gates, fixtures | Ad-hoc test setup, no coverage requirements |
262
263## Developer Experience Metrics (SPACE Framework)
264
265Measure platform effectiveness using the SPACE framework. Never rely on a single dimension.
266
267| Dimension | What It Measures | Example Metrics | Collection Method |
268|-----------|-----------------|-----------------|-------------------|
269| **S**atisfaction | How developers feel about the platform | NPS score, satisfaction survey (1-5) | Quarterly survey |
270| **P**erformance | Outcome of developer work | Deployment frequency, change failure rate | DORA metrics pipeline |
271| **A**ctivity | Volume of actions | Scaffolding requests, API calls, portal visits | Platform telemetry |
272| **C**ommunication | Quality of collaboration | Time to first response on platform support | Ticketing system |
273| **E**fficiency | Flow and minimal friction | Time from commit to deploy, onboarding time | Pipeline metrics |
274
275### Key DevEx Metrics Dashboard
276
277```yaml
278# Platform DevEx Metrics -- collected via platform telemetry
279metrics:
280 onboarding:
281 time_to_first_deploy:
282 target: "< 2 hours"
283 description: "Time from new hire to first successful deployment"
284 source: "scaffolder + pipeline timestamps"
285
286 time_to_first_commit:
287 target: "< 4 hours"
288 description: "Time from repo creation to first merged commit"
289 source: "github events"
290
291 self_service:
292 template_adoption_rate:
293 target: "> 80%"
294 description: "Percentage of new services using golden path templates"
295 source: "backstage scaffolder logs"
296
297 self_service_resolution_rate:
298 target: "> 70%"
299 description: "Percentage of requests resolved without platform team intervention"
300 source: "support tickets vs portal actions"
301
302 reliability:
303 platform_availability:
304 target: "99.9%"
305 description: "Uptime of developer portal, CI/CD, and artifact registry"
306 source: "synthetic monitoring"
307
308 mean_time_to_recovery:
309 target: "< 30 minutes"
310 description: "Time to restore platform services after incident"
311 source: "incident management system"
312
313 delivery:
314 deployment_frequency:
315 target: "multiple per day per team"
316 description: "How often teams deploy to production"
317 source: "deployment pipeline events"
318
319 lead_time_for_changes:
320 target: "< 1 day"
321 description: "Time from commit to production"
322 source: "git + pipeline timestamps"
323```
324
325## Self-Service Portal Workflow
326
327### Request Flow Architecture
328
329```
330Developer submits request via Portal UI
331 |
332 v
333Request Validation (schema check, policy check)
334 |
335 v
336Approval Gate (if required by policy)
337 | |
338 | auto | manual
339 v v
340Orchestration Engine (executes workflow)
341 |
342 +---> Provision Infrastructure (Terraform/Crossplane)
343 +---> Configure CI/CD (GitHub Actions / ArgoCD)
344 +---> Register in Catalog (Backstage)
345 +---> Set Up Monitoring (Grafana / PagerDuty)
346 +---> Notify Team (Slack / Email)
347 |
348 v
349Verification (health checks, smoke tests)
350 |
351 v
352Developer notified -- ready to use
353```
354
355### Self-Service Capability Matrix
356
357| Capability | Automation Level | Approval Required | Typical Time |
358|------------|-----------------|-------------------|--------------|
359| Create new service | Fully automated | No | 5 minutes |
360| Provision database | Fully automated | No (dev/staging), Yes (prod) | 10 minutes |
361| Add CI/CD pipeline | Fully automated | No | 2 minutes |
362| Request cloud credentials | Semi-automated | Yes (security review) | 1 hour |
363| Create new environment | Fully automated | No (non-prod), Yes (prod) | 15 minutes |
364| Add monitoring/alerts | Fully automated | No | 5 minutes |
365| Resize infrastructure | Semi-automated | Yes (cost review > threshold) | 30 minutes |
366| Decommission service | Automated with safeguards | Yes (owner confirmation) | 10 minutes |
367
368## Platform Engineering Maturity Model
369
370| Level | Name | Characteristics | Capabilities |
371|-------|------|----------------|--------------|
372| 0 | Ad Hoc | No platform, tribal knowledge | Teams manage their own infra |
373| 1 | Reactive | Shared scripts, wiki docs | Basic CI/CD, manual provisioning |
374| 2 | Standardized | Golden paths, basic portal | Service templates, catalog, basic self-service |
375| 3 | Optimized | Full IDP, metrics-driven | Self-service everything, DevEx metrics, policy-as-code |
376| 4 | Strategic | Platform as product, innovation | API-first platform, marketplace, continuous feedback |
377
378### Maturity Assessment Checklist
379
380```
381Level 1 --> Level 2:
382 [x] Service catalog exists and is maintained
383 [x] At least 3 golden path templates available
384 [x] Basic developer portal deployed
385 [x] CI/CD standardized across teams
386
387Level 2 --> Level 3:
388 [x] Self-service for >80% of common requests
389 [x] SPACE metrics collected and reviewed monthly
390 [x] Policy-as-code enforced (not advisory)
391 [x] Platform team has dedicated product manager
392 [x] Internal SLOs defined for platform services
393
394Level 3 --> Level 4:
395 [x] API-first platform (all capabilities programmable)
396 [x] Internal developer marketplace for plugins/extensions
397 [x] Continuous developer experience research program
398 [x] Platform economics model (cost attribution per team)
399 [x] Platform contributes to organizational strategy
400```
401
402## Anti-Patterns
403
404| Anti-Pattern | Problem | Fix |
405|--------------|---------|-----|
406| Build it and they will come | No adoption without developer input | Treat platform as product; user research before building |
407| Ticket-ops disguised as platform | Self-service portal that just creates tickets | Automate end-to-end; tickets are a smell, not a solution |
408| Mandating platform use | Forced adoption breeds resentment and workarounds | Make the golden path the easiest path, not the only path |
409| One-size-fits-all templates | Overly rigid templates that don't fit team needs | Composable templates with sensible defaults and escape hatches |
410| No feedback loops | Platform team builds in isolation | Regular surveys, office hours, embedded rotations with teams |
411| Ignoring developer experience | Technically correct but painful to use | Measure DevEx metrics, optimize for developer happiness |
412| Platform team as bottleneck | All changes go through platform team | Self-service with guardrails; teams should not wait on platform |
413| Over-abstracting too early | Complex abstraction layers before understanding needs | Start with concrete solutions, abstract when patterns emerge |
414| Neglecting documentation | Powerful platform nobody knows how to use | Docs-as-code, TechDocs in Backstage, examples for everything |
415| No platform SLOs | Platform reliability treated as best-effort | Define and publish SLOs; platform is a product with SLAs |
416| Shadow platforms | Teams build their own tooling around the platform | Understand why and address gaps; shadow platforms reveal unmet needs |
417| Gold plating the portal | Spending months on portal UI before delivering value | Ship incrementally; a working CLI beats a beautiful but empty portal |
418
419## Platform Engineering Checklist
420
421- [ ] Platform team established with clear product ownership
422- [ ] Developer portal deployed (Backstage or equivalent)
423- [ ] Service catalog populated with all production services
424- [ ] At least 3 golden path templates available and documented
425- [ ] Self-service provisioning for common infrastructure (databases, queues, caches)
426- [ ] CI/CD pipelines standardized and available via templates
427- [ ] Observability stack integrated (dashboards auto-created with new services)
428- [ ] Security scanning built into golden paths (not bolted on after)
429- [ ] DevEx metrics defined and collected (SPACE framework dimensions)
430- [ ] Feedback mechanism active (surveys, office hours, Slack channel)
431- [ ] Platform SLOs defined and monitored
432- [ ] Documentation maintained in developer portal (TechDocs)
433- [ ] Onboarding time measured and optimized (target: first deploy < 2 hours)
434- [ ] Cost visibility per team/service available through platform
435- [ ] Platform roadmap published and informed by developer feedback
436- [ ] Escape hatches documented for when golden paths don't fit
437- [ ] Platform reliability meets or exceeds published SLOs