Kubernetes is the de facto container orchestration layer for most organizations running at scale. It's also famously complex. In 2026, the dominant response to that complexity is the Internal Developer Platform (IDP) — a self-service layer that abstracts infrastructure operations so application developers don't have to understand the full Kubernetes stack.
The Problem with Bare Kubernetes
Deploying a simple web application to Kubernetes requires a Deployment, a Service, an Ingress, a ConfigMap, likely a Secret, and probably a HorizontalPodAutoscaler. Each is a separate YAML file with its own schema. Add RBAC rules, namespace policies, and resource quotas, and the operational surface becomes significant.
Most application developers don't need to understand all of this — and expecting them to creates a bottleneck. The infrastructure team fields constant questions; developers wait for approvals; no one is doing their best work.
What an IDP Provides
An IDP sits between developers and the infrastructure. Its job is to translate developer intent ("I need a web service with 2 replicas and a PostgreSQL database") into the correct infrastructure configuration.
The typical stack looks like this:
[Developer interface]
Web portal / CLI / API
↓
[Service catalog & templates]
Pre-approved application patterns
↓
[Infrastructure abstraction]
Helm / Crossplane / Terraform
↓
[Kubernetes clusters]
The developer interacts only with the top layer. The machinery underneath generates compliant, reproducible infrastructure.
Backstage as the IDP Frontend
Backstage (open-sourced by Spotify) has become the standard choice for the developer portal layer. It provides a service catalog, Software Templates for new service bootstrapping, and a plugin ecosystem that surfaces Kubernetes status, logs, and metrics in one place.
# catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: payment-service
description: Payment processing microservice
annotations:
github.com/project-slug: myorg/payment-service
backstage.io/kubernetes-id: payment-service
spec:
type: service
lifecycle: production
owner: payments-team
system: e-commerce
providesApis:
- payment-apiOnce a service is registered, developers can see its deployment status and recent deployments without direct kubectl access.
Standardizing New Services with Software Templates
One of the highest-value IDP features is the ability to bootstrap new services from a template. A developer fills out a form; the template generates a repository with CI/CD, a Helm chart, and namespace configuration already wired up.
# template.yaml (Backstage Software Template)
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: web-service-template
title: Standard Web Service
spec:
parameters:
- title: Service Details
required: [name, owner, replicas]
properties:
name:
type: string
title: Service name
owner:
type: string
title: Owning team
replicas:
type: integer
title: Replica count
default: 2
minimum: 1
maximum: 10
steps:
- id: fetch-template
name: Fetch template
action: fetch:template
input:
url: ./skeleton
values:
name: ${{ parameters.name }}
owner: ${{ parameters.owner }}
replicas: ${{ parameters.replicas }}
- id: publish
name: Create repository
action: publish:github
input:
repoUrl: github.com?repo=${{ parameters.name }}&owner=myorgThe skeleton the template generates includes a Dockerfile, GitHub Actions pipeline, Helm chart, and a pull request to request the Kubernetes namespace. The developer writes none of it.
Crossplane for Infrastructure Resources
Databases, queues, and storage buckets need to be provisioned alongside application code. Crossplane extends the Kubernetes API to manage cloud resources as custom resources, so developers can claim infrastructure through the same declarative workflow they use for applications.
# database-claim.yaml
apiVersion: database.platform.io/v1alpha1
kind: PostgreSQLInstance
metadata:
name: payment-db
namespace: payments
spec:
parameters:
storageGB: 20
tier: standard
writeConnectionSecretToRef:
name: payment-db-credentialsApply this, and Crossplane provisions an RDS instance (or Cloud SQL, depending on your composition) and drops the connection string into a Kubernetes Secret. The developer never touches the cloud console.
Common Pitfalls
Over-abstraction. If the IDP doesn't support an edge case, developers either work around it in unsupported ways or file tickets for the platform team. Keep documented escape hatches — ways to drop to raw Kubernetes YAML when needed.
Discoverability. An IDP that developers don't know about or can't navigate is wasted infrastructure. The service catalog's search and browsing experience needs as much investment as the underlying machinery.
Governance without friction. Self-service doesn't mean uncontrolled. Resource quotas, cost allocation tags, and security policy enforcement need to be baked into the templates and abstractions from the start — not bolted on afterward.
When to Build vs. When to Keep It Simple
Building an IDP on top of Backstage and Crossplane makes sense when your organization manages more than a handful of teams and dozens of services. The fixed cost of maintaining Backstage plugins and Crossplane compositions pays off at that scale.
For smaller organizations, well-written Helm charts, standardized GitHub Actions workflows, and a clear runbook wiki often deliver 80% of the benefit with 20% of the complexity.
Takeaway
IDPs don't solve Kubernetes — they hide the parts of it that most developers don't need to understand. The platform team becomes a product team, building internal tools that multiply the leverage of every application developer in the organization.
Start small: identify the most repeated manual steps in your current deployment process, and automate one at a time. A software template that saves 2 hours per new service pays back its development cost after a handful of services.