Crossplane vs Terraform vs Pulumi: Which IaC Approach in 2026?
Crossplane, Terraform, and Pulumi compared for infrastructure as code in 2026 — Kubernetes-native continuous reconciliation vs plan-apply workflows, drift handling, and which model fits your platform team's architecture.
Crossplane isn't really competing on the same axis as Terraform and Pulumi — it's a fundamentally different execution model (continuous Kubernetes-native reconciliation vs plan-then-apply) wearing similar "provision cloud infrastructure" clothing. Understanding that difference matters more than a feature checklist.
Quick Comparison
| Crossplane | Terraform | Pulumi | |
|---|---|---|---|
| Execution model | Continuous reconciliation (Kubernetes controllers) | Plan-then-apply, run on demand or in CI | Plan-then-apply, run on demand or in CI |
| Drift handling | Automatic — continuously corrects drift | Detected on next plan, not automatic | Detected on next plan, not automatic |
| Language | YAML (Composition/Claim) or KRM-based | HCL | Real programming languages (TS, Python, Go, etc.) |
| Kubernetes-native | Yes — IS a Kubernetes controller/CRD system | No — external tool | No — external tool |
| Self-service abstraction | Strong (Compositions expose simplified Claims to app teams) | Requires modules + wrapper tooling | Requires component resources + wrapper tooling |
| Maturity/ecosystem | Newer, smaller provider ecosystem | Most mature, largest provider ecosystem | Mature, growing ecosystem |
Crossplane
Crossplane turns cloud infrastructure into Kubernetes custom resources, managed by controllers that continuously reconcile actual state to desired state — the same model Kubernetes uses for Pods and Deployments, applied to AWS/GCP/Azure resources.
# A Composition defines HOW to build infrastructure (platform team writes this)
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: postgres-database
spec:
compositeTypeRef:
apiVersion: platform.example.com/v1alpha1
kind: XPostgresDatabase
resources:
- name: rdsinstance
base:
apiVersion: rds.aws.crossplane.io/v1alpha1
kind: DBInstance
spec:
forProvider:
engine: postgres
instanceClass: db.t3.medium# App teams request infrastructure via a simple Claim (self-service, abstracted)
apiVersion: platform.example.com/v1alpha1
kind: PostgresDatabase
metadata:
name: my-app-db
spec:
size: mediumCrossplane strengths:
- Continuous reconciliation means drift is automatically corrected, not just detected on the next scheduled run — a resource manually changed in the console gets reverted automatically
- Genuinely strong self-service model — platform teams build Compositions once, app teams request infrastructure through simple Claims without touching cloud provider details
- Being a Kubernetes controller means it fits naturally into GitOps tooling (ArgoCD/Flux) already managing your cluster — no separate state backend to manage
- No separate state file to lock/corrupt — Kubernetes' etcd is the source of truth
Crossplane weaknesses:
- Smaller provider ecosystem than Terraform's — coverage of less-common cloud services lags behind
- YAML-based Compositions can get genuinely complex for non-trivial infrastructure logic, without the expressiveness of a real language or even HCL's functions
- Requires running and operating a Kubernetes cluster as the control plane, even for teams not otherwise Kubernetes-centric
- Steeper conceptual learning curve — understanding Compositions, Claims, and XRDs is a real onboarding cost
When to use Crossplane: You're already Kubernetes-native, want continuous drift correction, and need a strong self-service abstraction layer for app teams provisioning their own infrastructure.
Terraform
Terraform remains the default choice for most teams — HCL-based, plan-then-apply, with by far the largest provider ecosystem and community.
resource "aws_db_instance" "postgres" {
engine = "postgres"
instance_class = "db.t3.medium"
allocated_storage = 20
}Terraform strengths:
- Largest provider ecosystem by a wide margin — if a cloud service exists, a Terraform provider almost certainly supports it
- Explicit plan-then-apply workflow gives a clear review step before changes hit infrastructure — many teams value this human checkpoint
- Massive community, documentation, and existing organizational expertise — the safest default for hiring and onboarding
- Works identically regardless of whether you use Kubernetes anywhere
Terraform weaknesses:
- Drift is only detected on the next
plan, not corrected automatically — infrastructure can silently diverge between runs - State file management (locking, backend configuration) is real operational overhead, especially at scale
- HCL, while purpose-built, is less expressive than a general-purpose language for complex conditional logic
When to use Terraform: The safe default for most teams — broadest ecosystem, most hiring pool familiarity, works regardless of your platform's Kubernetes adoption.
Pulumi
Pulumi takes Terraform's plan-then-apply model but lets you write infrastructure in real programming languages instead of a DSL.
import * as aws from "@pulumi/aws";
const postgres = new aws.rds.Instance("postgres", {
engine: "postgres",
instanceClass: "db.t3.medium",
allocatedStorage: 20,
});Pulumi strengths:
- Real programming languages mean real loops, conditionals, functions, and testing frameworks — genuinely more expressive for complex infrastructure logic
- Type safety catches errors at compile time that HCL only catches at plan time
- Easier to share logic with application code if your team already writes TypeScript/Python/Go elsewhere
Pulumi weaknesses:
- Same fundamental drift-detection-not-correction model as Terraform — no automatic reconciliation
- Smaller ecosystem and community than Terraform, though larger than Crossplane's
- The "just write code" flexibility can be a double-edged sword — infrastructure logic can get as messy as application code without discipline
When to use Pulumi: Your team already thinks in TypeScript/Python/Go and wants that expressiveness for infrastructure, without a hard requirement for Kubernetes-native continuous reconciliation.
The Honest Verdict
Kubernetes-native platform, want continuous drift correction and strong self-service abstractions: Crossplane. The architectural fit is genuinely different from the other two, not just a syntax preference.
Default safe choice, broadest ecosystem, works regardless of your stack: Terraform. Still the right default for most teams in 2026.
Team already fluent in a real programming language, wants that expressiveness: Pulumi. Same execution model as Terraform, more familiar syntax for software engineers.
The real decision axis isn't "which syntax do I prefer" — it's whether you want continuous reconciliation (Crossplane) or explicit plan-apply control (Terraform/Pulumi), and that's an architectural decision, not a stylistic one.
More IaC comparisons? Read our Terraform vs OpenTofu vs Pulumi and How to set up Crossplane on Kubernetes.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
ArgoCD vs Spinnaker vs Flux: GitOps Continuous Delivery Comparison 2026
ArgoCD, Spinnaker, and Flux CD compared for Kubernetes continuous delivery in 2026 — GitOps approach, multi-cluster support, canary/blue-green deployments, UI, RBAC, and which fits startups vs enterprises.
AWS EKS vs Self-Managed Kubernetes in 2026: Which to Choose
EKS vs running Kubernetes yourself on EC2 — compared on cost, operational burden, control plane HA, upgrades, and when self-managed actually makes sense for teams in 2026.
AWS Fargate vs EKS vs Lambda: Which for Running Containers in 2026?
AWS Fargate, EKS (on EC2), and Lambda containers compared for 2026 — cold start time, cost at different scales, operational overhead, and which to pick for your workload pattern.