Back to articles
Technology Insight

Building Enterprise Developer Platforms with Backstage, Score, and Crossplane

August 22, 2026

Building Enterprise Internal Developer Platforms with Backstage, Score, and Crossplane

As enterprises scale their multi-cloud footprint across AWS, GCP, and Azure, developer cognitive load has reached a critical breaking point. Software engineers are frequently forced to navigate complex Cloud Provider Consoles, intricate Infrastructure-as-Code (IaC) templates (Terraform/Pulumi), and raw Kubernetes YAML manifests just to ship a single microservice. This fragmentation creates severe operational bottlenecks, security governance gaps, and shadow IT.

To solve this, leading DevOps organizations are building Internal Developer Platforms (IDPs). This article explores a battle-tested architecture combining three open-source pillars: Backstage (Developer Portal UX & Service Catalog), Score (Environment-agnostic Workload Specification Standard), and Crossplane (Kubernetes-native Universal Control Plane).

The Modern IDP Triad Architecture

An enterprise-grade IDP must enforce a clean separation of concerns between Platform Engineers (who construct infrastructure abstractions and governance guardrails) and Application Developers (who consume resources and deploy workloads).

  • Backstage (Single Pane of Glass): Provides the unified developer portal, cataloging microservices, documentation, software templates, and real-time observability indicators.
  • Score (Workload Abstraction Layer): Provides an open-source, developer-centric specification (score.yaml) that abstracts application requirements (containers, environment variables, dependent resources like databases and queues) away from target environments.
  • Crossplane (Universal Control Plane): Extends Kubernetes CRDs to orchestrate multi-cloud infrastructure directly via the Kubernetes API, replacing traditional asynchronous IaC pipelines with continuous reconciliation loops.

The architectural control loop operates as follows:

+-----------------------------------------------------------------------------------+
|                                 DEVELOPER REALM                                   |
|  +------------------------+                     +------------------------------+  |
|  |   Backstage Portal     |  --- (Scaffold) --> | Git Repo (code + score.yaml) |  |
|  |  (Catalog & Scaffolder)|                     +------------------------------+  |
|  +------------------------+                                    |                  |
+----------------------------------------------------------------|------------------+
                                                                 | Git Push / CI
                                                                 v
+-----------------------------------------------------------------------------------+
|                                PLATFORM REALM                                     |
|  +------------------------+                     +------------------------------+  |
|  |  score-k8s / Translator| --- (Generates) --> | Crossplane Claims & K8s Spec |  |
|  +------------------------+                     +------------------------------+  |
|                                                                |                  |
|                                                         ArgoCD / GitOps           |
|                                                                v                  |
|  +-----------------------------------------------------------------------------+  |
|  |                        Kubernetes Platform Cluster                          |  |
|  |  +--------------------+                     +----------------------------+  |  |
|  |  | Application Pods   |                     | Crossplane Control Plane   |  |  |
|  |  +--------------------+                     +----------------------------+  |  |
|  +-----------------------------------------------------------|-----------------+  |
+--------------------------------------------------------------|--------------------+
                                                               | API Reconciliation
                                                               v
                                    +----------------------------------------------------+
                                    | Multi-Cloud Infrastructure (AWS RDS, GCP SQL, etc) |
                                    +----------------------------------------------------+

1. Crossplane: Abstracting Cloud Infrastructure with Compositions

Platform engineers define reusable, compliance-checked infrastructure building blocks using Crossplane Composite Resource Definitions (XRDs) and Compositions. Below is an XRD defining a unified SQL database resource that abstract away whether the implementation is AWS RDS or GCP CloudSQL.

# definition.yaml: CompositeResourceDefinition (XRD)
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresinstances.platform.enterprise.io
spec:
  group: platform.enterprise.io
  names:
    kind: XPostgresInstance
    plural: xpostgresinstances
  claimNames:
    kind: PostgresInstance
    plural: postgresinstances
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                storageGB:
                  type: integer
                  default: 20
                engineVersion:
                  type: string
                  default: "15"
              required:
                - storageGB

Next, the platform team maps this XRD to concrete provider resources using a Crossplane Composition tailored for AWS RDS:

# composition-aws.yaml: Composition mapping to AWS RDS
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xpostgresinstance.aws.rds
  labels:
    provider: aws
    db: postgresql
spec:
  compositeTypeRef:
    apiVersion: platform.enterprise.io/v1alpha1
    kind: XPostgresInstance
  resources:
    - name: rds-instance
      base:
        apiVersion: database.aws.upbound.io/v1beta1
        kind: Instance
        spec:
          forProvider:
            region: us-east-1
            dbSubnetGroupName: enterprise-vpc-subnets
            engine: postgres
            instanceClass: db.t4g.medium
            allocatedStorage: 20
            skipFinalSnapshot: true
            publiclyAccessible: false
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.storageGB
          toFieldPath: spec.forProvider.allocatedStorage
        - type: FromCompositeFieldPath
          fromFieldPath: spec.engineVersion
          toFieldPath: spec.forProvider.engine

2. Score: Standardizing the Workload Specification

Instead of requiring developers to write raw Kubernetes Deployments, Services, and Crossplane Resource Claims, developers specify workload intentions using a declarative score.yaml.

# score.yaml: Developer Workload Specification
apiVersion: score.dev/v1b1
metadata:
  name: payment-service
containers:
  web:
    image: 123456789.dkr.ecr.us-east-1.amazonaws.com/payment-service:v2.4.1
    variables:
      PORT: "8080"
      DB_HOST: "${resources.db.host}"
      DB_NAME: "${resources.db.name}"
      DB_USER: "${resources.db.username}"
      DB_PASSWORD: "${resources.db.password}"
resources:
  db:
    type: postgres
    properties:
      host: metadata.name
      name: metadata.database
      username: status.username
      password: status.password

During the CI/CD pipeline, the CLI tool score-k8s or custom Score translators convert this file into native Kubernetes manifests alongside a Crossplane PostgresInstance claim. The developer never touches cloud credentials or raw RDS manifests.

3. Backstage: Integrating Catalog and Scaffolder

Backstage acts as the central developer portal. Using Backstage Software Templates, developers can initiate new microservices with built-in cloud infrastructure without leaving the UI.

Below is a Backstage Scaffolder Template snippet that generates a microservice repo containing the application boilerplate and the score.yaml file:

# template.yaml: Backstage Software Template
apiVersion: backstage.io/v1alpha1
kind: Template
metadata:
  name: golang-microservice-template
  title: Go Microservice with Managed PostgreSQL
  description: Creates a Go microservice integrated with Crossplane-provisioned Postgres DB via Score spec.
spec:
  owner: platform-team
  type: service
  parameters:
    - title: Service Configuration
      required:
        - serviceName
        - dbStorageSize
      properties:
        serviceName:
          title: Service Name
          type: string
          default: order-processing
        dbStorageSize:
          title: Database Storage (GB)
          type: integer
          default: 50
  steps:
    - id: fetch-base
      name: Fetch Template Code
      action: fetch:template
      url: ./template
      values:
        serviceName: ${{ parameters.serviceName }}
        dbStorageSize: ${{ parameters.dbStorageSize }}

    - id: publish-git
      name: Publish to GitHub
      action: publish:github
      input:
        allowedOwners: ['enterprise-org']
        repoUrl: 'github.com?repo=' + parameters.serviceName + '&owner=enterprise-org'

    - id: register-catalog
      name: Register Component in Backstage
      action: catalog:register
      input:
        catalogInfoUrl: 'https://github.com/enterprise-org/' + parameters.serviceName + '/blob/main/catalog-info.yaml'

Enterprise Governance, Policy Enforcement, and GitOps

A resilient IDP requires strict runtime validation and zero manual drift. By implementing ArgoCD alongside Open Policy Agent (OPA) / Kyverno, platform teams can enforce regulatory compliance across the entire pipeline:

  1. Policy Enforcement at the Kubernetes API Layer: Kyverno policies inspect incoming Crossplane Composite Resources (XRs) to enforce mandatory tags (e.g., cost-center, owner) and restrict maximum storage limits.
  2. Continuous Drift Reconciliation: Crossplane continually compares actual multi-cloud infrastructure state against the Kubernetes API state, automatically reverting unauthorized modifications in AWS or GCP.
  3. Secure Secret Injection: Secrets generated by Crossplane (e.g., RDS database credentials) are stored directly into HashiCorp Vault or Kubernetes Secrets, which are then dynamically mapped into the application Pod environment by the Score resource resolver.

Conclusion

Combining Backstage, Score, and Crossplane establishes a high-velocity, secure Internal Developer Platform. Backstage eliminates portal fragmentation, Score shields developers from Kubernetes and infrastructure verbosity, and Crossplane transforms Kubernetes into a universal multi-cloud control plane. This modern stack empowers application developers to self-serve complete stacks in minutes while enabling platform engineers to enforce security, compliance, and cost control across multi-cloud enterprise footprints.