For years, the industry standard for managing cloud resources has been a ‘push-based’ model. You write a Terraform file, run terraform apply, and hope the state file doesn’t get corrupted in a git merge conflict. But as I’ve scaled my own projects, I found that the gap between ‘infrastructure’ and ‘application’ deployment was creating a cognitive load that slowed down my team.

That’s where my journey into a crossplane review and architecture analysis began. Crossplane isn’t just another tool; it’s a fundamental shift. Instead of treating infrastructure as a script to be run, Crossplane treats it as a set of resources to be managed by a control plane—specifically, the Kubernetes control plane.

The Challenge: The ‘Drift’ and the ‘Silo’

In my experience with traditional IaC, the biggest pain point is drift. Someone manually changes a security group rule in the AWS Console, and suddenly your Terraform code is a lie. You only find out during the next planned deployment, which often leads to catastrophic failures because the ‘real world’ no longer matches the ‘code world’.

Furthermore, we’ve historically separated the people who manage the VPC (Infrastructure team) from the people who manage the Pods (App team). This creates a ticket-based bottleneck. When I’m looking for the best IaC tools for Kubernetes, I’m not just looking for a way to spin up a cluster; I’m looking for a way to unify the entire lifecycle.

Solution Overview: The Control Plane Philosophy

Crossplane transforms your Kubernetes cluster into a universal control plane. It uses Custom Resource Definitions (CRDs) to represent cloud resources. Want an S3 bucket? You don’t run a CLI command; you apply a YAML file to Kubernetes. The Crossplane controller then works tirelessly in the background to ensure that the actual state of the cloud matches your YAML definition.

As shown in the architecture diagram above, Crossplane abstracts the cloud provider’s API behind a Kubernetes-native interface. This means you can use kubectl get buckets to see your AWS S3 buckets just as you would check your deployments.

Deep Dive: Crossplane Architecture

To understand Crossplane, you have to understand its three core architectural pillars: Providers, Managed Resources, and Compositions.

1. Providers

Providers are the ‘drivers’ of Crossplane. They are installed as pods in your cluster and handle the translation between the Kubernetes API and the Cloud API (e.g., AWS, Azure, GCP). I’ve found that the provider-aws is incredibly robust, though the sheer volume of available resources can be overwhelming at first.

2. Managed Resources (MRs)

An MR is a 1:1 mapping to a cloud resource. For example, a Bucket resource in Crossplane maps directly to an S3 bucket in AWS. This is the most basic level of the architecture.

3. Compositions and XRs

This is where the magic happens. Compositions allow me to create my own ‘Custom APIs’. Instead of asking a developer to define a VPC, three subnets, and an RDS instance, I can create a CompositeResourceDefinition (XRD) called PostgresInstance. The developer just requests a PostgresInstance, and Crossplane expands that into the 15 different AWS resources required to make it work securely. This aligns perfectly with modern IaC trends 2026, where the goal is ‘platform engineering’ rather than just ‘infrastructure as code’.

Implementation: Creating a Managed Database

Here is a simplified example of how I implement a managed resource. First, we define the Composite Resource (the ‘interface’ for my developers):

# xrd.yaml
apiVersion: apiextensions.crossplane.io/v1beta1
kind: CompositeResourceDefinition
metadata:
  name: xpostgresinstances.database.ajmani.dev
spec:
  group: database.ajmani.dev
  names:
    kind: XPostgresInstance
    plural: xpostgresinstances
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        type: object
        properties:
          storageGb: { type: integer }

Then, I define the Composition (the ‘implementation’ that maps to AWS):

# composition.yaml
apiVersion: apiextensions.crossplane.io/v1beta1
kind: Composition
metadata:
  name: aws-postgres
  labels:
    provider: aws
spec:
  compositeTypeRef:
    apiVersion: database.ajmani.dev/v1alpha1
    kind: XPostgresInstance
  resources:
    - base:
        apiVersion: database.aws.upbound.io/v1beta1
        kind: DBInstance
        spec:
          dbInstanceClass: db.t3.micro
          engine: postgres
      patches:
        - fromFieldPath: "spec.storageGb"
          toFieldPath: "spec.forProvider.allocatedStorage"

Finally, the developer just applies a simple claim:

# claim.yaml
apiVersion: database.ajmani.dev/v1alpha1
kind: PostgresInstance
metadata:
  name: my-app-db
  namespace: app-prod
spec:
  storageGb: 20
Terminal output showing a Crossplane resource transitioning from Unhealthy to Ready state
Terminal output showing a Crossplane resource transitioning from Unhealthy to Ready state

Case Study: Moving from Terraform to Crossplane

In a recent project, I migrated a microservices stack consisting of 12 services, each requiring its own RDS instance and SQS queue. In Terraform, this meant managing 12 different state files or one massive, fragile state file. With Crossplane, I created a single ServiceInfrastructure composition.

The result? Onboarding a new service went from 2 days of DevOps tickets to 5 minutes of applying a YAML file. More importantly, the ‘drift’ was eliminated. When a developer accidentally changed a database parameter in the AWS console, Crossplane detected it within minutes and reverted it to the state defined in Git.

Pitfalls and Trade-offs

It’s not all sunshine. Crossplane has a steep learning curve. If you aren’t comfortable with Kubernetes CRDs and the kubectl ecosystem, you will struggle. I’ve also noticed that debugging can be harder than in Terraform; you aren’t looking at a plan output, you’re digging through pod logs to figure out why a resource is stuck in SYNCING state.

Additionally, your Kubernetes cluster becomes a single point of failure for your infrastructure. If the cluster goes down, you can’t easily update your infrastructure unless you have a secondary management path.

Final Verdict

Crossplane is a powerhouse for organizations moving toward a Platform Engineering model. It removes the friction between development and operations by treating the cloud as an extension of the Kubernetes API. While it’s overkill for a small side project, for any team managing complex, multi-tenant cloud environments, the architecture is superior to traditional push-based IaC.