Platform Engineering & Internal Developer Platforms : construire un IDP avec Backstage

Publié le 17 janvier 2026

DevOps
Platform Engineering
Kubernetes

90% des organisations utilisent au moins un Internal Developer Platform en 2026. Le Platform Engineering réduit le cognitive load des développeurs tout en standardisant infrastructure et sécurité. Guide complet avec Backstage.

Plan

  • Qu'est-ce que le Platform Engineering ?
  • Architecture d'un Internal Developer Platform
  • Backstage : le framework IDP de référence
  • Implémenter golden paths et templates
  • Self-service infrastructure avec Terraform
  • Portal catalog et documentation
  • Intégration CI/CD et observabilité
  • Mesurer le succès d'un IDP
  • Conclusion

Qu'est-ce que le Platform Engineering ?

Définition et contexte 2026

Platform Engineering = discipline qui construit et maintient des Internal Developer Platforms (IDP) pour améliorer la developer experience et standardiser les pratiques.

Problème résolu :

  • Équipes DevOps submergées de tickets (provision infra, debug)
  • Développeurs bloqués par complexité Kubernetes/cloud
  • Outils fragmentés (10-30 outils différents)
  • Knowledge silos et duplication d'efforts
  • Onboarding nouveaux développeurs : 2-4 semaines

Solution IDP :

  • Self-service portal (provision en 5 minutes)
  • Golden paths (templates pré-configurés)
  • Abstraction complexité infrastructure
  • Documentation centralisée
  • Standardisation sécurité/observabilité

Statistiques 2026

  • 90% des organisations utilisent ≥1 IDP
  • 40% réduction tickets DevOps après IDP
  • 70% réduction temps onboarding (2 semaines → 2 jours)
  • 35% amélioration déploiement frequency
  • Platform Engineer = 5ème poste tech le plus demandé

Platform Engineering vs DevOps

AspectDevOps traditionnelPlatform Engineering
FocusCI/CD, automationDeveloper experience
ApprocheOutils éparpillésPlateforme unifiée
Self-serviceLimitéCentral
AbstractionFaibleHaute (golden paths)
Cognitive loadÉlevéRéduit
TicketsNombreux-40%

Architecture d'un Internal Developer Platform

Composants essentiels

┌─────────────────────────────────────────────────┐
│           Developer Portal (Backstage)          │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │ Catalog  │  │Templates │  │ Documentation│  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────┘
                      ↓
┌─────────────────────────────────────────────────┐
│              Control Plane                      │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │GitOps    │  │ Policy   │  │ Secrets      │  │
│  │(ArgoCD)  │  │(OPA)     │  │ (Vault)      │  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────┘
                      ↓
┌─────────────────────────────────────────────────┐
│           Infrastructure Layer                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │Kubernetes│  │Terraform │  │ Cloud APIs   │  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────┘
                      ↓
┌─────────────────────────────────────────────────┐
│          Observability & Security               │
│  ┌──────────┐  ┌──────────┐  ┌──────────────┐  │
│  │Prometheus│  │ Logs     │  │ Security     │  │
│  │Grafana   │  │(Loki)    │  │ Scanning     │  │
│  └──────────┘  └──────────┘  └──────────────┘  │
└─────────────────────────────────────────────────┘

Principe : Platform as a Product

Traiter l'IDP comme un produit :

  • Product manager dédié
  • Roadmap features
  • User feedback loops
  • SLA/SLO pour la plateforme
  • Internal NPS (Net Promoter Score)

Équipe Platform typique :

  • 1 Product Manager
  • 3-5 Platform Engineers
  • 1 Technical Writer
  • Ratio : 1 platform engineer pour 30-50 developers

Backstage : le framework IDP de référence

Pourquoi Backstage ?

Backstage = open-source IDP framework créé par Spotify, adopté par Netflix, American Airlines, Zalando, DAZN.

Avantages :

  • Open source (Apache 2.0)
  • Extensible (plugins)
  • Communauté active (200+ plugins)
  • Intégrations natives (GitHub, GitLab, Kubernetes, AWS, etc.)
  • Templates Scaffolder puissants

Installation Backstage

# Prérequis
node --version  # v18+
yarn --version

# Créer app Backstage
npx @backstage/create-app@latest

# Nom : my-platform
cd my-platform

# Structure générée :
# packages/
#   app/         # Frontend React
#   backend/     # Backend Node.js
# plugins/       # Plugins custom
# app-config.yaml

# Démarrer dev
yarn dev
# Frontend: http://localhost:3000
# Backend: http://localhost:7007

Configuration initiale

# app-config.yaml

app:
  title: Engineering Platform
  baseUrl: https://platform.company.com

organization:
  name: MyCompany

backend:
  baseUrl: https://platform.company.com
  listen:
    port: 7007
  
  database:
    client: pg
    connection:
      host: ${POSTGRES_HOST}
      port: ${POSTGRES_PORT}
      user: ${POSTGRES_USER}
      password: ${POSTGRES_PASSWORD}
  
  cors:
    origin: https://platform.company.com

# Intégrations
integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}
  
  gitlab:
    - host: gitlab.company.com
      token: ${GITLAB_TOKEN}

# Catalog (source des entities)
catalog:
  rules:
    - allow: [Component, System, API, Resource, Location]
  
  locations:
    # Fichier local
    - type: file
      target: ../../catalog-info.yaml
    
    # Org GitHub
    - type: url
      target: https://github.com/myorg/backstage-catalog/blob/main/all.yaml
      rules:
        - allow: [User, Group]

# Auth (GitHub OAuth)
auth:
  environment: production
  providers:
    github:
      production:
        clientId: ${GITHUB_CLIENT_ID}
        clientSecret: ${GITHUB_CLIENT_SECRET}

Déploiement production

Option 1 : Kubernetes (recommandé)

# kubernetes/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backstage
  namespace: platform
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backstage
  template:
    metadata:
      labels:
        app: backstage
    spec:
      containers:
      - name: backstage
        image: backstage:v1.0.0
        ports:
        - containerPort: 7007
        env:
        - name: POSTGRES_HOST
          value: postgresql.platform.svc.cluster.local
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: backstage-secrets
              key: postgres-password
        - name: GITHUB_TOKEN
          valueFrom:
            secretKeyRef:
              name: backstage-secrets
              key: github-token
        livenessProbe:
          httpGet:
            path: /healthcheck
            port: 7007
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"

---
apiVersion: v1
kind: Service
metadata:
  name: backstage
  namespace: platform
spec:
  selector:
    app: backstage
  ports:
  - port: 80
    targetPort: 7007

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: backstage
  namespace: platform
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  tls:
  - hosts:
    - platform.company.com
    secretName: backstage-tls
  rules:
  - host: platform.company.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backstage
            port:
              number: 80
# Build image
yarn tsc
yarn build:backend
docker build -t backstage:v1.0.0 .

# Deploy
kubectl apply -f kubernetes/

Implémenter golden paths et templates

Qu'est-ce qu'un Golden Path ?

Golden Path = chemin pré-configuré et opinionné pour créer un nouveau service/application respectant les best practices.

Exemple : "Créer une API Node.js"

  • Repository GitHub créé
  • CI/CD configuré (GitHub Actions)
  • Kubernetes manifests générés
  • Observabilité intégrée (Prometheus, logs)
  • Security scanning activé
  • Documentation générée

Créer un template Backstage

# templates/nodejs-api/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: nodejs-api
  title: Node.js API Service
  description: Create a new Node.js REST API with best practices
  tags:
    - nodejs
    - api
    - recommended
spec:
  owner: platform-team
  type: service
  
  parameters:
    - title: Service Info
      required:
        - name
        - description
        - owner
      properties:
        name:
          title: Name
          type: string
          description: Unique service name
          pattern: '^[a-z0-9-]+$'
        description:
          title: Description
          type: string
          description: What does this service do?
        owner:
          title: Owner
          type: string
          description: Team owning this service
          ui:field: OwnerPicker
          ui:options:
            allowedKinds:
              - Group
    
    - title: Infrastructure
      properties:
        cpu:
          title: CPU Limit
          type: string
          enum:
            - "500m"
            - "1000m"
            - "2000m"
          default: "1000m"
        memory:
          title: Memory Limit
          type: string
          enum:
            - "512Mi"
            - "1Gi"
            - "2Gi"
          default: "1Gi"
        replicas:
          title: Replicas
          type: integer
          default: 2
          minimum: 1
          maximum: 10
  
  steps:
    # 1. Fetch template base
    - id: fetch-base
      name: Fetch Base
      action: fetch:template
      input:
        url: ./skeleton
        values:
          name: ${{ parameters.name }}
          description: ${{ parameters.description }}
          owner: ${{ parameters.owner }}
    
    # 2. Create GitHub repo
    - id: publish
      name: Publish to GitHub
      action: publish:github
      input:
        allowedHosts: ['github.com']
        description: ${{ parameters.description }}
        repoUrl: github.com?owner=myorg&repo=${{ parameters.name }}
        repoVisibility: internal
        defaultBranch: main
    
    # 3. Create Kubernetes manifests
    - id: create-k8s-manifests
      name: Create K8s Manifests
      action: fetch:template
      input:
        url: ./k8s-skeleton
        targetPath: ./k8s
        values:
          name: ${{ parameters.name }}
          cpu: ${{ parameters.cpu }}
          memory: ${{ parameters.memory }}
          replicas: ${{ parameters.replicas }}
    
    # 4. Register in catalog
    - id: register
      name: Register Component
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
        catalogInfoPath: '/catalog-info.yaml'
  
  output:
    links:
      - title: Repository
        url: ${{ steps.publish.output.remoteUrl }}
      - title: Open in catalog
        icon: catalog
        entityRef: ${{ steps.register.output.entityRef }}

Skeleton template

templates/nodejs-api/skeleton/
├── .github/
│   └── workflows/
│       └── ci.yaml
├── src/
│   ├── index.js
│   ├── routes/
│   └── middleware/
├── tests/
│   └── api.test.js
├── Dockerfile
├── package.json
├── README.md
└── catalog-info.yaml
# templates/nodejs-api/skeleton/catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: ${{values.name}}
  description: ${{values.description}}
  annotations:
    github.com/project-slug: myorg/${{values.name}}
    backstage.io/kubernetes-id: ${{values.name}}
    prometheus.io/rule: ${{values.name}}
  tags:
    - nodejs
    - api
  links:
    - url: https://${{values.name}}.company.com
      title: Production
      icon: web
spec:
  type: service
  lifecycle: production
  owner: ${{values.owner}}
  system: platform
  providesApis:
    - ${{values.name}}-api

Self-service infrastructure avec Terraform

Intégrer Terraform dans IDP

Objectif : Permettre aux développeurs de provisionner infra via UI sans connaître Terraform.

Architecture :

Backstage Template
      ↓
  GitOps Repo (PR auto)
      ↓
  Atlantis / Terraform Cloud
      ↓
  Infrastructure provisioned
      ↓
  Catalog updated

Plugin Terraform pour Backstage

// packages/app/src/components/catalog/EntityPage.tsx

import { EntityTerraformContent } from '@roadiehq/backstage-plugin-terraform';

const serviceEntityPage = (
  <EntityLayout>
    <EntityLayout.Route path="/" title="Overview">
      <Grid container spacing={3}>
        <Grid item md={6}>
          <EntityAboutCard />
        </Grid>
      </Grid>
    </EntityLayout.Route>
    
    <EntityLayout.Route path="/terraform" title="Infrastructure">
      <EntityTerraformContent />
    </EntityLayout.Route>
  </EntityLayout>
);

Template avec Terraform

# templates/aws-rds-postgres/template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: aws-rds-postgres
  title: AWS RDS PostgreSQL Database
  description: Provision managed PostgreSQL database
spec:
  owner: platform-team
  type: resource
  
  parameters:
    - title: Database Configuration
      properties:
        dbName:
          title: Database Name
          type: string
        instanceClass:
          title: Instance Class
          type: string
          enum:
            - db.t3.micro
            - db.t3.small
            - db.t3.medium
            - db.r5.large
          default: db.t3.small
        storageSize:
          title: Storage (GB)
          type: integer
          default: 20
  
  steps:
    - id: fetch-terraform
      name: Fetch Terraform Module
      action: fetch:template
      input:
        url: ./terraform
        values:
          dbName: ${{ parameters.dbName }}
          instanceClass: ${{ parameters.instanceClass }}
          storageSize: ${{ parameters.storageSize }}
    
    - id: publish-terraform
      name: Create Terraform PR
      action: publish:github:pull-request
      input:
        repoUrl: github.com?owner=myorg&repo=terraform-infra
        branchName: add-db-${{ parameters.dbName }}
        title: Add RDS PostgreSQL ${{ parameters.dbName }}
        description: |
          Automated PR from Backstage IDP
          
          Database: ${{ parameters.dbName }}
          Instance: ${{ parameters.instanceClass }}
          Storage: ${{ parameters.storageSize }}GB
# templates/aws-rds-postgres/terraform/main.tf
resource "aws_db_instance" "${{values.dbName}}" {
  identifier        = "${{values.dbName}}"
  engine            = "postgres"
  engine_version    = "14.7"
  instance_class    = "${{values.instanceClass}}"
  allocated_storage = ${{values.storageSize}}
  
  db_name  = "${{values.dbName}}"
  username = "admin"
  password = random_password.db_password.result
  
  vpc_security_group_ids = [aws_security_group.db.id]
  db_subnet_group_name   = aws_db_subnet_group.db.name
  
  backup_retention_period = 7
  backup_window          = "03:00-04:00"
  maintenance_window     = "Mon:04:00-Mon:05:00"
  
  enabled_cloudwatch_logs_exports = ["postgresql"]
  
  tags = {
    Name        = "${{values.dbName}}"
    ManagedBy   = "Backstage"
    Environment = "production"
  }
}

resource "random_password" "db_password" {
  length  = 32
  special = true
}

resource "aws_secretsmanager_secret" "db_password" {
  name = "rds/${{values.dbName}}/password"
}

resource "aws_secretsmanager_secret_version" "db_password" {
  secret_id     = aws_secretsmanager_secret.db_password.id
  secret_string = random_password.db_password.result
}

output "endpoint" {
  value = aws_db_instance.${{values.dbName}}.endpoint
}

output "secret_arn" {
  value = aws_secretsmanager_secret.db_password.arn
}

Portal catalog et documentation

Software Catalog

Catalog = inventaire centralisé de tous les composants (services, APIs, resources, teams).

Entities types :

  • Component : service, library, website
  • API : interface REST, GraphQL, gRPC
  • Resource : database, S3 bucket, queue
  • System : collection de components
  • Domain : collection de systems
  • User : personne
  • Group : équipe

Exemple catalog-info.yaml complet

# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: payment-service
  description: Handles payment processing
  annotations:
    # GitHub
    github.com/project-slug: myorg/payment-service
    
    # Kubernetes
    backstage.io/kubernetes-id: payment-service
    backstage.io/kubernetes-namespace: production
    
    # CI/CD
    github.com/workflows: ci.yaml,release.yaml
    
    # Observability
    prometheus.io/rule: payment-service-alerts
    grafana/dashboard-selector: payment-service
    
    # Security
    snyk.io/org-id: org-abc123
    sonarqube.org/project-key: payment-service
    
    # Documentation
    backstage.io/techdocs-ref: dir:.
  
  tags:
    - nodejs
    - payment
    - pci-dss
  
  links:
    - url: https://payment.company.com
      title: Production
      icon: web
    - url: https://wiki.company.com/payment-service
      title: Wiki
      icon: docs
    - url: https://pagerduty.com/services/payment-service
      title: PagerDuty
      icon: alert

spec:
  type: service
  lifecycle: production
  owner: payments-team
  system: checkout
  
  dependsOn:
    - resource:default/postgres-payments
    - resource:default/redis-cache
    - component:default/fraud-detection
  
  providesApis:
    - payment-api
  
  consumesApis:
    - stripe-api
    - paypal-api

---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: payment-api
  description: Payment processing API
spec:
  type: openapi
  lifecycle: production
  owner: payments-team
  system: checkout
  definition: |
    openapi: 3.0.0
    info:
      title: Payment API
      version: 1.0.0
    paths:
      /payments:
        post:
          summary: Create payment
          requestBody:
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    amount:
                      type: number
                    currency:
                      type: string

TechDocs (documentation)

TechDocs = docs-as-code avec MkDocs, intégrées dans Backstage.

# mkdocs.yml
site_name: Payment Service
site_description: Documentation for payment processing service

nav:
  - Home: index.md
  - Architecture: architecture.md
  - API Reference: api.md
  - Runbooks: runbooks.md
  - Security: security.md

theme:
  name: material

plugins:
  - techdocs-core
# docs/index.md

# Payment Service

## Overview
The payment service handles all payment transactions...

## Quick Start
```bash
npm install
npm run dev

Architecture

Architecture diagram

API Documentation

See API Reference


**Génération docs :**

```bash
# Local
npx @techdocs/cli generate

# CI/CD (GitHub Actions)
- name: Generate TechDocs
  uses: backstage/techdocs-container-action@v1

Intégration CI/CD et observabilité

Plugin GitHub Actions

# app-config.yaml
integrations:
  github:
    - host: github.com
      token: ${GITHUB_TOKEN}
// packages/app/src/components/catalog/EntityPage.tsx
import { EntityGithubActionsContent } from '@backstage/plugin-github-actions';

<EntityLayout.Route path="/ci-cd" title="CI/CD">
  <EntityGithubActionsContent />
</EntityLayout.Route>

Plugin Kubernetes

# app-config.yaml
kubernetes:
  serviceLocatorMethod:
    type: 'multiTenant'
  clusterLocatorMethods:
    - type: 'config'
      clusters:
        - url: https://k8s-prod.company.com
          name: production
          authProvider: 'serviceAccount'
          serviceAccountToken: ${K8S_TOKEN}
          skipTLSVerify: false
          caData: ${K8S_CA_DATA}
// Entity page
import { EntityKubernetesContent } from '@backstage/plugin-kubernetes';

<EntityLayout.Route path="/kubernetes" title="Kubernetes">
  <EntityKubernetesContent />
</EntityLayout.Route>

Plugin Prometheus / Grafana

// packages/app/src/components/catalog/EntityPage.tsx
import { EntityPrometheusContent } from '@roadiehq/backstage-plugin-prometheus';
import { EntityGrafanaDashboardsCard } from '@k-phoen/backstage-plugin-grafana';

<EntityLayout.Route path="/monitoring" title="Monitoring">
  <Grid container spacing={3}>
    <Grid item md={12}>
      <EntityPrometheusContent />
    </Grid>
    <Grid item md={12}>
      <EntityGrafanaDashboardsCard />
    </Grid>
  </Grid>
</EntityLayout.Route>

Mesurer le succès d'un IDP

Métriques Platform Engineering

Developer Experience (DevEx) :

  • Time to first deployment (nouveau dev)
  • Self-service adoption rate
  • Ticket reduction (DevOps team)
  • Developer satisfaction (NPS)

Efficiency :

  • Deployment frequency
  • Lead time for changes
  • MTTR (Mean Time To Recovery)
  • Environment provisioning time

Quality :

  • Security scan coverage
  • Policy compliance rate
  • Documentation coverage
  • Golden path adoption

Tableau de bord IDP

# Métriques Prometheus
platform_template_usage{template="nodejs-api"} 45
platform_catalog_entities{type="component"} 234
platform_self_service_requests_total 1234
platform_ticket_reduction_percent 42
platform_onboarding_time_days 2

Grafana dashboard :

  • Services créés / semaine
  • Time to first deploy (tendance)
  • Top templates utilisés
  • Tickets DevOps évités
  • Coverage sécurité/docs

Survey Developer Experience

# Quarterly survey
Questions:
  - "How satisfied are you with the platform? (1-10)"
  - "How easy is it to create a new service? (1-10)"
  - "How often do you need to contact DevOps? (daily/weekly/monthly/rarely)"
  - "What feature would you like to see next?"

Target NPS:  50

Checklist implémentation IDP

Phase 1 : Foundation (Semaine 1-4)

  • Backstage installé et déployé
  • Auth configuré (GitHub OAuth)
  • Catalog initial (teams, existing services)
  • 1er golden path (service simple)
  • Documentation portal actif

Phase 2 : Adoption (Semaine 5-12)

  • 3-5 golden paths disponibles
  • Self-service infra (Terraform)
  • CI/CD intégration
  • Kubernetes plugin actif
  • 20%+ services dans catalog

Phase 3 : Scale (Mois 3-6)

  • Observabilité intégrée
  • Security scanning automatique
  • TechDocs généralisé
  • 60%+ services dans catalog
  • Metrics IDP collectées

Phase 4 : Optimize (Mois 6+)

  • NPS Developer ≥50
  • 80%+ adoption golden paths
  • <40% réduction tickets DevOps
  • <2 jours onboarding
  • Custom plugins développés

Conclusion

Le Platform Engineering avec un IDP comme Backstage réduit drastiquement le cognitive load des développeurs tout en standardisant infrastructure, sécurité et observabilité. L'adoption massive en 2026 (90%) confirme que c'est devenu un standard.

Points clés :

  • IDP = plateforme self-service pour developers
  • Backstage = framework open source mature
  • Golden paths = best practices automatisées
  • Platform as a Product = mentalité requise
  • Mesurer DevEx et adoption essentiels

Gains typiques :

  • Onboarding : -70% (2 semaines → 2 jours)
  • Tickets DevOps : -40%
  • Time to production : -60%
  • Security compliance : +80%
  • Developer satisfaction : +50 NPS

Actions prioritaires :

  1. Installer Backstage (POC en 1 semaine)
  2. Créer 1er golden path (Node.js ou Python API)
  3. Importer services existants dans catalog
  4. Mesurer baseline (onboarding time, tickets)
  5. Itérer avec feedback developers
Besoin d'aide sur ce sujet ?

Notre équipe d'experts est là pour vous accompagner dans vos projets.

Contactez-nous

Articles similaires qui pourraient vous intéresser