Back to Blog
5 min read

The Rise of Platform Engineering in 2022

Platform engineering emerged as a distinct discipline in 2022, evolving from DevOps to address developer experience at scale. Let’s explore what it means and how to get started.

What is Platform Engineering?

Platform engineering is the practice of building and maintaining internal developer platforms (IDPs) that enable self-service capabilities for development teams.

The goal: Reduce cognitive load on developers while maintaining governance and best practices.

The Problem It Solves

# Before platform engineering
developer_tasks = [
    "Write application code",
    "Create Kubernetes manifests",
    "Set up CI/CD pipelines",
    "Configure monitoring",
    "Manage secrets",
    "Set up databases",
    "Configure networking",
    "Handle security scanning",
    "Manage certificates",
    "Deal with infrastructure"
]

# With platform engineering
developer_tasks = [
    "Write application code",
    "Define requirements in spec file",
    "Push code"  # Platform handles the rest
]

Internal Developer Platform Components

1. Service Catalog

# Backstage catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payment-service
  description: Handles payment processing
  annotations:
    backstage.io/techdocs-ref: dir:.
    github.com/project-slug: company/payment-service
    pagerduty.com/service-id: PXXXXXX
  tags:
    - python
    - payments
    - critical
  links:
    - url: https://grafana.company.com/d/payment
      title: Grafana Dashboard
    - url: https://payment-service.docs.company.com
      title: API Documentation
spec:
  type: service
  lifecycle: production
  owner: team-payments
  system: e-commerce
  providesApis:
    - payment-api
  dependsOn:
    - resource:default/payment-db
    - component:default/fraud-detection

2. Golden Paths / Templates

# Backstage Software Template
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: dotnet-api-template
  title: .NET API Service
  description: Create a new .NET API with all best practices
  tags:
    - recommended
    - dotnet
    - api
spec:
  owner: platform-team
  type: service

  parameters:
    - title: Service Information
      required:
        - name
        - description
        - owner
      properties:
        name:
          title: Service Name
          type: string
          pattern: '^[a-z0-9-]+$'
        description:
          title: Description
          type: string
        owner:
          title: Owner Team
          type: string
          ui:field: OwnerPicker

    - title: Technical Options
      properties:
        database:
          title: Database Type
          type: string
          enum:
            - postgresql
            - cosmosdb
            - none
        messaging:
          title: Messaging System
          type: string
          enum:
            - servicebus
            - eventhubs
            - none

  steps:
    - id: fetch-base
      name: Fetch Base Template
      action: fetch:template
      input:
        url: ./skeleton
        values:
          name: ${{ parameters.name }}
          description: ${{ parameters.description }}
          owner: ${{ parameters.owner }}

    - id: create-repo
      name: Create Repository
      action: publish:github
      input:
        repoUrl: github.com?owner=company&repo=${{ parameters.name }}
        description: ${{ parameters.description }}

    - id: create-infrastructure
      name: Provision Infrastructure
      action: http:backstage:request
      input:
        method: POST
        path: /api/platform/provision
        body:
          service: ${{ parameters.name }}
          database: ${{ parameters.database }}
          messaging: ${{ parameters.messaging }}

    - id: register-catalog
      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
        url: ${{ steps['register-catalog'].output.catalogInfoUrl }}

3. Self-Service Infrastructure

# Platform API - Service provisioning
openapi: 3.0.0
info:
  title: Platform Provisioning API
  version: 1.0.0

paths:
  /api/services:
    post:
      summary: Provision a new service
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ServiceRequest'
      responses:
        '202':
          description: Provisioning started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ProvisioningStatus'

components:
  schemas:
    ServiceRequest:
      type: object
      required:
        - name
        - team
        - environment
      properties:
        name:
          type: string
          pattern: '^[a-z0-9-]+$'
        team:
          type: string
        environment:
          type: string
          enum: [dev, staging, production]
        resources:
          type: object
          properties:
            compute:
              type: string
              enum: [small, medium, large]
            database:
              type: object
              properties:
                type:
                  type: string
                  enum: [postgresql, cosmosdb]
                size:
                  type: string
                  enum: [basic, standard, premium]
            cache:
              type: boolean
            messageQueue:
              type: boolean

4. Developer Portal

// Backstage plugin for environment management
import React from 'react';
import { useEntity } from '@backstage/plugin-catalog-react';
import { Table, TableColumn } from '@backstage/core-components';

export const EnvironmentTable = () => {
  const { entity } = useEntity();
  const environments = useEnvironments(entity.metadata.name);

  const columns: TableColumn[] = [
    { title: 'Environment', field: 'name' },
    { title: 'Status', field: 'status' },
    { title: 'Version', field: 'version' },
    { title: 'Last Deployed', field: 'lastDeployed' },
    {
      title: 'Actions',
      render: (row) => (
        <>
          <Button onClick={() => deploy(row.name)}>Deploy</Button>
          <Button onClick={() => rollback(row.name)}>Rollback</Button>
          <Button onClick={() => viewLogs(row.name)}>Logs</Button>
        </>
      ),
    },
  ];

  return (
    <Table
      title="Environments"
      options={{ paging: false }}
      columns={columns}
      data={environments}
    />
  );
};

Platform Team Structure

platform_team:
  size: 5-10 engineers (for ~100 developers)

  roles:
    - name: Platform Lead
      focus: Strategy, stakeholder management
      count: 1

    - name: Platform Engineer
      focus: IDP development, automation
      count: 3-5

    - name: SRE
      focus: Reliability, observability
      count: 2-3

    - name: Security Engineer
      focus: DevSecOps, policies
      count: 1-2

  responsibilities:
    - Developer portal maintenance
    - Golden path templates
    - CI/CD platform
    - Observability stack
    - Security tooling
    - Documentation
    - Developer support

  metrics:
    - Time to first deployment (new service)
    - Developer satisfaction score
    - Platform adoption rate
    - Incident reduction
    - Self-service completion rate

Implementation Roadmap

roadmap = {
    "phase_1_foundation": {
        "duration": "3 months",
        "goals": [
            "Establish platform team",
            "Select core technologies",
            "Build first golden path",
            "Deploy developer portal"
        ]
    },
    "phase_2_self_service": {
        "duration": "3 months",
        "goals": [
            "Self-service environments",
            "Automated provisioning",
            "Integrated CI/CD",
            "Basic observability"
        ]
    },
    "phase_3_adoption": {
        "duration": "3 months",
        "goals": [
            "Migrate existing services",
            "Expand golden paths",
            "Advanced observability",
            "Cost visibility"
        ]
    },
    "phase_4_optimization": {
        "duration": "ongoing",
        "goals": [
            "Performance optimization",
            "Advanced automation",
            "AI/ML integration",
            "Continuous improvement"
        ]
    }
}

Success Metrics

platform_metrics = {
    "developer_experience": {
        "time_to_first_deploy": "< 1 day",
        "self_service_rate": "> 90%",
        "developer_satisfaction": "> 4.0/5",
        "documentation_coverage": "> 95%"
    },
    "operational": {
        "platform_availability": "> 99.9%",
        "mean_time_to_provision": "< 15 minutes",
        "incident_rate": "decreasing trend",
        "support_tickets": "decreasing trend"
    },
    "business": {
        "deployment_frequency": "increasing trend",
        "lead_time": "decreasing trend",
        "developer_productivity": "increasing trend",
        "infrastructure_cost": "optimized"
    }
}

Common Pitfalls

  1. Building too much: Start small, iterate
  2. Ignoring developer feedback: Platform is for developers
  3. Forcing adoption: Make it attractive, not mandatory
  4. Over-engineering: Simple solutions often win
  5. Neglecting documentation: Docs are part of the product

Conclusion

Platform engineering represents the evolution of DevOps at scale. By providing self-service capabilities with built-in guardrails, organizations can accelerate development while maintaining consistency and governance. The key is treating the platform as a product, with developers as the customers.

Resources

Michael John Peña

Michael John Peña

Senior Data Engineer based in Sydney. Writing about data, cloud, and technology.