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

Pulumi vs AWS CDK vs Crossplane — Modern IaC Tools 2026

Terraform is the default but Pulumi, AWS CDK, and Crossplane are growing fast. Here's when each makes sense and how they compare to each other.

DevOpsBoysJun 2, 20264 min read
Share:Tweet

Terraform is the IaC standard. But Pulumi, AWS CDK, and Crossplane are each winning in specific scenarios. Here's the honest comparison.


Why Look Beyond Terraform?

Terraform is great. But it has real limitations:

  • HCL is not a programming language — loops, conditionals, functions are awkward
  • Testing infrastructure code is hard
  • Sharing and reusing code (modules) is verbose

The alternatives address these specifically.


Pulumi

Write infrastructure in Python, TypeScript, Go, C#, or Java. Full programming language — real loops, conditionals, functions, testing frameworks.

Example: EKS Cluster in Python

python
import pulumi
import pulumi_aws as aws
import pulumi_eks as eks
 
# Real Python — use variables, loops, functions naturally
env = pulumi.get_stack()  # "dev", "staging", "prod"
 
vpc = aws.ec2.Vpc(
    f"{env}-vpc",
    cidr_block="10.0.0.0/16",
    enable_dns_hostnames=True,
    tags={"Environment": env}
)
 
# Python dict comprehension — try this in HCL
subnet_ids = []
for i, az in enumerate(["us-east-1a", "us-east-1b", "us-east-1c"]):
    subnet = aws.ec2.Subnet(
        f"{env}-subnet-{i}",
        vpc_id=vpc.id,
        cidr_block=f"10.0.{i}.0/24",
        availability_zone=az,
        map_public_ip_on_launch=True
    )
    subnet_ids.append(subnet.id)
 
cluster = eks.Cluster(
    f"{env}-cluster",
    vpc_id=vpc.id,
    subnet_ids=subnet_ids,
    instance_type="t3.medium",
    desired_capacity=2,
    min_size=1,
    max_size=10,
)
 
pulumi.export("kubeconfig", cluster.kubeconfig)

Pulumi Strengths

  • Real programming language — Python/TypeScript testing frameworks, type safety, IDE support
  • Multi-cloud — same SDK for AWS, GCP, Azure, Kubernetes, 100+ providers
  • Pulumi Cloud — managed state backend (free tier available)
  • Converts Terraformpulumi convert --from terraform migrates existing HCL

Pulumi Weaknesses

  • Smaller community than Terraform (but growing fast)
  • Pulumi Cloud required for team features (or self-host backend)
  • Language-specific bugs can be subtle

Best for

  • Teams who prefer writing Python/TypeScript over HCL
  • Complex infrastructure with lots of conditional logic
  • Teams who want to test infrastructure code with pytest/jest

AWS CDK (Cloud Development Kit)

AWS CDK lets you define AWS infrastructure in TypeScript, Python, Java, C#, or Go. It compiles down to CloudFormation.

Example: ECS Service in TypeScript

typescript
import * as cdk from 'aws-cdk-lib';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecsp from 'aws-cdk-lib/aws-ecs-patterns';
 
export class MyServiceStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
 
    // CDK handles VPC, cluster, load balancer, IAM — all in 10 lines
    new ecsp.ApplicationLoadBalancedFargateService(this, 'MyService', {
      taskImageOptions: {
        image: ecs.ContainerImage.fromRegistry('nginx:latest'),
        containerPort: 80,
      },
      publicLoadBalancer: true,
      desiredCount: 2,
      cpu: 256,
      memoryLimitMiB: 512,
    });
  }
}

CDK Strengths

  • Higher-level abstractionsApplicationLoadBalancedFargateService creates 15+ AWS resources in one construct
  • AWS-native — best-in-class support for every AWS service
  • CDK Constructs Library — reusable community constructs
  • AWS-supported — first-class AWS tooling and docs

CDK Weaknesses

  • AWS-only — no multi-cloud support (CDK for Terraform exists but is different)
  • CloudFormation backend means CloudFormation's quirks and limits
  • Some complex scenarios need CloudFormation knowledge

Best for

  • AWS-only teams who want high-level abstractions
  • Teams who already use TypeScript
  • When you want one construct that creates an entire service

Crossplane

Crossplane extends Kubernetes to manage cloud infrastructure. You define AWS/GCP/Azure resources as Kubernetes CRDs.

Example: RDS Database via Kubernetes YAML

yaml
# PostgreSQL RDS instance as a Kubernetes resource
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
  name: production-db
spec:
  forProvider:
    region: us-east-1
    instanceClass: db.t3.micro
    engine: postgres
    engineVersion: "15.4"
    dbName: myapp
    username: admin
    allocatedStorage: 20
    skipFinalSnapshot: true
  writeConnectionSecretToRef:
    namespace: default
    name: db-connection  # Creates K8s secret with connection string
bash
kubectl apply -f postgres.yaml
kubectl get instance production-db
# NAME             READY   SYNCED   AGE
# production-db    True    True     5m

The RDS instance shows up in kubectl get just like a pod.

Composition — Define Your Own Abstractions

yaml
# Define a "PostgresDatabase" composite resource
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresdatabases.devops.example.com
spec:
  names:
    kind: XPostgresDatabase
  claimNames:
    kind: PostgresDatabase
  # ... define what fields dev teams can set

Now developers request a database like this:

yaml
# Developer's request — they don't need to know AWS details
apiVersion: devops.example.com/v1alpha1
kind: PostgresDatabase
metadata:
  name: my-app-db
spec:
  parameters:
    size: small   # Platform team defines what "small" means in AWS terms
    region: us-east-1

Crossplane Strengths

  • Kubernetes-native — same tools, same RBAC, same GitOps workflows
  • Self-service platforms — developers request infrastructure without knowing AWS
  • GitOps compatible — ArgoCD/Flux manage cloud resources like app manifests
  • Multi-cloud — provider for AWS, GCP, Azure, and many more

Crossplane Weaknesses

  • Complex setup — Crossplane + providers + compositions is significant overhead
  • Kubernetes dependency — requires a running cluster
  • Steep learning curve — Compositions and XRDs are powerful but complex
  • Not Terraform replacement — better for platform teams, not individual DevOps

Best for

  • Platform engineering teams building self-service developer portals
  • Organizations standardizing on Kubernetes for everything
  • Teams doing GitOps and want cloud resources in the same workflow

Head-to-Head

PulumiAWS CDKCrossplane
LanguagePython/TS/Go/C#TS/Python/Java/C#YAML (Kubernetes)
Multi-cloud❌ AWS only
Kubernetes nativeVia provider✅ Native
Learning curveMediumMediumHigh
State managementPulumi Cloud/S3CloudFormationKubernetes etcd
Best forGeneral IaCAWS-heavy teamsPlatform Engineering

Choose Pulumi if you hate HCL but don't want to go Kubernetes-native.
Choose CDK if you're AWS-only and want high-level constructs.
Choose Crossplane if you're building a self-service developer platform on Kubernetes.
Keep Terraform if your team is productive with it and there's no specific pain point.

Learn all IaC tools with hands-on practice at KodeKloud — Terraform, Pulumi, and Kubernetes all have dedicated courses.

🔧

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