🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

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.

Shubham4 min read
Share:Tweet

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

CrossplaneTerraformPulumi
Execution modelContinuous reconciliation (Kubernetes controllers)Plan-then-apply, run on demand or in CIPlan-then-apply, run on demand or in CI
Drift handlingAutomatic — continuously corrects driftDetected on next plan, not automaticDetected on next plan, not automatic
LanguageYAML (Composition/Claim) or KRM-basedHCLReal programming languages (TS, Python, Go, etc.)
Kubernetes-nativeYes — IS a Kubernetes controller/CRD systemNo — external toolNo — external tool
Self-service abstractionStrong (Compositions expose simplified Claims to app teams)Requires modules + wrapper toolingRequires component resources + wrapper tooling
Maturity/ecosystemNewer, smaller provider ecosystemMost mature, largest provider ecosystemMature, 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.

yaml
# 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
yaml
# 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: medium

Crossplane 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.

hcl
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.

typescript
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

Browse fixes
Newsletter

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

Comments