Platform Engineering with Golden Paths
Platform Engineering golden paths represent the evolution of DevOps into a product-oriented discipline focused on developer self-service. Instead of requiring every team to configure their own CI/CD pipelines, infrastructure, monitoring, and security controls, platform teams build standardized “golden paths” — opinionated, pre-configured templates that embody organizational best practices and enable developers to ship features faster.
This guide covers building an Internal Developer Platform (IDP) with golden path templates using Backstage, Crossplane, and ArgoCD. Moreover, you will learn how to balance standardization with flexibility, measure platform adoption, and evolve your golden paths based on developer feedback.
What Makes a Golden Path
A golden path is not a mandate — it is the path of least resistance that also happens to be the path of best practice. When creating a new microservice is as simple as filling out a form and clicking “Create,” developers naturally choose the platform’s golden path over hand-rolling their own infrastructure. Furthermore, golden paths encode security controls, observability standards, and compliance requirements so developers get them automatically.
The key components of a golden path include service templates (scaffolding), infrastructure templates (cloud resources), CI/CD pipeline templates, observability templates (dashboards, alerts), and documentation templates. Each template should be opinionated but customizable — covering 80% of use cases out of the box while allowing escape hatches for the remaining 20%.
Platform Engineering: Backstage Service Catalog
Spotify’s Backstage serves as the frontend for most IDPs, providing a service catalog, software templates, and a plugin ecosystem. Therefore, it becomes the single pane of glass where developers discover services, create new ones, and access documentation.
# backstage-template.yaml — Golden path service 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 cloud infrastructure.
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-]*$'
description: Lowercase with hyphens (e.g., order-service)
owner:
title: Team Owner
type: string
ui:field: OwnerPicker
ui:options:
catalogFilter:
kind: Group
description:
title: Description
type: string
maxLength: 200
tier:
title: Service Tier
type: string
enum: [tier-1-critical, tier-2-important, tier-3-standard]
default: tier-3-standard
- title: Technical Configuration
properties:
javaVersion:
title: Java Version
type: string
enum: ["21", "17"]
default: "21"
database:
title: Database
type: string
enum: [postgresql, mysql, none]
default: postgresql
messaging:
title: Message Broker
type: string
enum: [kafka, rabbitmq, none]
default: none
caching:
title: Cache
type: string
enum: [redis, none]
default: none
- title: Infrastructure
properties:
environment:
title: Environments
type: array
items:
type: string
enum: [dev, staging, production]
default: [dev, staging, production]
replicas:
title: Production Replicas
type: integer
default: 3
minimum: 2
maximum: 10
steps:
# Step 1: Generate service code from template
- id: fetch-skeleton
name: Fetch Service Skeleton
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
javaVersion: ${{ parameters.javaVersion }}
database: ${{ parameters.database }}
# Step 2: Create GitHub repository
- id: create-repo
name: Create Repository
action: publish:github
input:
repoUrl: github.com?owner=my-org&repo=${{ parameters.name }}
description: ${{ parameters.description }}
defaultBranch: main
protectDefaultBranch: true
requireCodeOwnerReviews: true
# Step 3: Provision infrastructure via Crossplane
- id: create-infrastructure
name: Provision Infrastructure
action: kubernetes:apply
input:
manifest:
apiVersion: platform.myorg.io/v1alpha1
kind: ServiceInfrastructure
metadata:
name: ${{ parameters.name }}
spec:
database: ${{ parameters.database }}
messaging: ${{ parameters.messaging }}
caching: ${{ parameters.caching }}
environments: ${{ parameters.environment }}
# Step 4: Register in Backstage catalog
- id: register
name: Register in Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps.create-repo.output.repoContentsUrl }}
catalogInfoPath: /catalog-info.yaml
output:
links:
- title: Repository
url: ${{ steps.create-repo.output.remoteUrl }}
- title: Service in Catalog
icon: catalog
entityRef: ${{ steps.register.output.entityRef }}Infrastructure Templates with Crossplane
Additionally, Crossplane enables platform teams to define infrastructure abstractions that developers consume without needing cloud provider expertise. Composite Resource Definitions (XRDs) create simplified APIs over complex cloud resources.
# composition.yaml — Database infrastructure abstraction
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: postgresql-standard
labels:
crossplane.io/xrd: xpostgresqlinstances.platform.myorg.io
spec:
compositeTypeRef:
apiVersion: platform.myorg.io/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
engine: postgres
engineVersion: "16"
instanceClass: db.t3.medium
allocatedStorage: 50
storageEncrypted: true
deletionProtection: true
autoMinorVersionUpgrade: true
backupRetentionPeriod: 7
monitoringInterval: 60
performanceInsightsEnabled: true
tags:
managed-by: crossplane
team: platform
patches:
- fromFieldPath: spec.parameters.size
toFieldPath: spec.forProvider.instanceClass
transforms:
- type: map
map:
small: db.t3.medium
medium: db.r6g.large
large: db.r6g.2xlarge
- name: parameter-group
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: ParameterGroup
spec:
forProvider:
family: postgres16
parameter:
- name: log_statement
value: "mod"
- name: log_min_duration_statement
value: "1000"
- name: shared_preload_libraries
value: "pg_stat_statements"Measuring Platform Success
Consequently, platform engineering is a product discipline — you need metrics to understand adoption, satisfaction, and impact. The DORA metrics (deployment frequency, lead time, MTTR, change failure rate) improve when golden paths work well.
# Platform metrics to track
metrics:
adoption:
- golden_path_usage_percentage # Target: > 80%
- template_creation_count # New services created via templates
- escape_hatch_usage # How often teams deviate from golden path
- time_to_first_deploy # How long from service creation to first deploy
satisfaction:
- developer_nps_score # Net Promoter Score for the platform
- support_ticket_volume # Should decrease over time
- self_service_success_rate # % of requests completed without help
impact:
- deployment_frequency # DORA metric
- lead_time_for_changes # DORA metric
- mean_time_to_recovery # DORA metric
- change_failure_rate # DORA metric
- security_vulnerability_count # Should decrease with golden paths
- compliance_audit_findings # Should decreaseWhen NOT to Use Platform Engineering
Small organizations (under 20 engineers) rarely benefit from building an IDP — the investment in platform tooling exceeds the productivity gains. A few well-documented runbooks and shared CI/CD templates achieve most of the benefit at a fraction of the cost. As a result, platform engineering makes economic sense when you have 5+ development teams creating similar services repeatedly.
Avoid building platforms in isolation from the developers who will use them. The most common failure mode is platform teams building what they think developers need rather than what developers actually need. Treat your platform as a product with user research, feedback loops, and iterative improvement.
Key Takeaways
Platform Engineering golden paths transform how organizations deliver software by making best practices the default choice. Backstage provides the developer portal, Crossplane abstracts infrastructure complexity, and ArgoCD automates deployments — together they create a self-service platform that scales with your organization. Furthermore, measuring adoption and developer satisfaction ensures your platform evolves based on real needs.
Start by identifying the most common developer workflow in your organization and build a golden path for it. For deeper exploration, see the Backstage documentation and the Platform Engineering community. Our posts on API gateway vs service mesh and feature flags and trunk-based development complement your platform strategy.