Platform engineering is the discipline of building and maintaining internal developer platforms (IDPs) that enable self-service capabilities for software engineering teams. The goal is to reduce cognitive load, standardize infrastructure provisioning, and accelerate delivery while maintaining governance and security guardrails.
Backstage is the leading open-source developer portal framework, originally created at Spotify.
# Prerequisites: Node.js 18+, yarn 1.x
npx @backstage/create-app@latest
# Follow the prompts -- name your app, e.g., "internal-platform"
cd internal-platform
# Start the development server
yarn dev
# Dockerfile for Backstage production image
FROM node:18-bookworm-slim AS build
WORKDIR /app
COPY package.json yarn.lock ./
COPY packages/ packages/
COPY plugins/ plugins/
RUN yarn install --frozen-lockfile
RUN yarn tsc
RUN yarn build:backend
FROM node:18-bookworm-slim
WORKDIR /app
COPY --from=build /app/packages/backend/dist/ ./
COPY --from=build /app/node_modules/ ./node_modules/
COPY app-config.yaml app-config.production.yaml ./
ENV NODE_ENV=production
CMD ["node", "packages/backend", "--config", "app-config.production.yaml"]
# app-config.yaml
app:
title: Internal Developer Platform
baseUrl: http://localhost:3000
organization:
name: MyOrg
backend:
baseUrl: http://localhost:7007
listen:
port: 7007
database:
client: pg
connection:
host: ${POSTGRES_HOST}
port: ${POSTGRES_PORT}
user: ${POSTGRES_USER}
password: ${POSTGRES_PASSWORD}
integrations:
github:
- host: github.com
token: ${GITHUB_TOKEN}
catalog:
import:
entityFilename: catalog-info.yaml
pullRequestBranchName: backstage-integration
rules:
- allow: [Component, System, API, Resource, Location, Template]
locations:
- type: url
target: https://github.com/myorg/software-catalog/blob/main/catalog-info.yaml
- type: url
target: https://github.com/myorg/backstage-templates/blob/main/all-templates.yaml
Crossplane extends Kubernetes to provision and manage cloud infrastructure through declarative YAML.
# Add the Crossplane Helm repo
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
# Install Crossplane into its own namespace
helm install crossplane crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace \
--set args='{"--enable-composition-revisions"}'
# Install the AWS provider
kubectl apply -f - <<EOF
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws
spec:
package: xpkg.upbound.io/upbound/provider-family-aws:v1.1.0
EOF
# Configure AWS credentials
kubectl create secret generic aws-creds \
-n crossplane-system \
--from-file=creds=./aws-credentials.txt
kubectl apply -f - <<EOF
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: creds
EOF
This defines a new platform API that developers consume without knowing the underlying cloud resources.
# xrd-application-database.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xapplicationdatabases.platform.myorg.io
spec:
group: platform.myorg.io
names:
kind: XApplicationDatabase
plural: xapplicationdatabases
claimNames:
kind: ApplicationDatabase
plural: applicationdatabases
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
engine:
type: string
enum: ["postgres", "mysql"]
default: "postgres"
engineVersion:
type: string
default: "15"
storageGB:
type: integer
minimum: 20
maximum: 500
default: 20
instanceSize:
type: string
enum: ["small", "medium", "large"]
default: "small"
environment:
type: string
enum: ["dev", "staging", "prod"]
required:
- environment
# composition-aws-database.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: applicationdatabase-aws
labels:
provider: aws
spec:
compositeTypeRef:
apiVersion: platform.myorg.io/v1alpha1
kind: XApplicationDatabase
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
region: us-east-1
allocatedStorage: 20
autoMinorVersionUpgrade: true
backupRetentionPeriod: 7
dbName: appdb
deletionProtection: false
publiclyAccessible: false
skipFinalSnapshot: true
storageEncrypted: true
storageType: gp3
vpcSecurityGroupIdSelector:
matchLabels:
platform.myorg.io/network: shared
dbSubnetGroupNameSelector:
matchLabels:
platform.myorg.io/network: shared
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.engine
toFieldPath: spec.forProvider.engine
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.engineVersion
toFieldPath: spec.forProvider.engineVersion
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.forProvider.allocatedStorage
- type: CombineFromComposite
combine:
variables:
- fromFieldPath: spec.parameters.instanceSize
strategy: map
map:
small: db.t3.micro
medium: db.t3.medium
large: db.r6g.large
toFieldPath: spec.forProvider.instanceClass
- name: db-secret
base:
apiVersion: secretstores.aws.upbound.io/v1beta1
kind: Secret
spec:
forProvider:
region: us-east-1
patches:
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.forProvider.name
transforms:
- type: string
string:
fmt: "platform/%s/db-credentials"
# my-app-database.yaml
apiVersion: platform.myorg.io/v1alpha1
kind: ApplicationDatabase
metadata:
name: orders-db
namespace: team-commerce
spec:
parameters:
engine: postgres
engineVersion: "15"
storageGB: 50
instanceSize: medium
environment: staging
Adopt platform engineering practices when your organization experiences:
Platform engineering is NOT about replacing ops with a portal. It is about encoding organizational standards into reusable, self-service abstractions that dev teams consume through golden paths.
git status && git diff --stat
kubectl diff -f manifest.yaml
Adapted from BagelHole/DevOps-Security-Agent-Skills (MIT); frontmatter, When to Use/Limitations, and safety boundaries added for upstream compliance. Docs-only import: helper scripts and templates not bundled.