Crossplane vs. Terraform: A comparison of the IaC tools
Crossplane and Terraform both infrastructure as code (IaC) solutions, but are used for different challenges in real environments. They both ultimately solve the same problem, managing your IaC, but come at it from two very different angles.
Terraform is a mature tool for defining infrastructure resources with a declarative language and applying those changes through explicit Terraform plan and apply steps. Crossplane extends a Kubernetes cluster into a universal control plane that can manage external resources such as cloud services, databases, and networks through Kubernetes custom resources, which live alongside application objects.
By the end, you will have a clear view of the aspects of Terraform vs. Crossplane at the technology level and at the workflow level, as well as concrete recommendations for when each approach fits your infrastructure management strategy.
What is Crossplane?
Crossplane is an open source control plane platform engineering framework that extends Kubernetes to manage external resources and in-cluster workloads. It uses the Kubernetes API and custom resources to represent cloud infrastructure databases, networks, message queues, and even entire Kubernetes clusters.
In practice, Crossplane runs inside a Kubernetes cluster and turns that cluster into a universal control plane for cloud infrastructure.
Crossplane providers connect this control plane to major cloud providers and other APIs. These providers translate Kubernetes custom resources into calls to the underlying cloud provider API, so a single Kubernetes API becomes your interface to cloud resources across AWS, Azure, Google Cloud, and other platforms.
Platform engineers define higher-level infrastructure platforms by composing multiple low-level resources into custom resources of their own. For example, they can define a CompositePostgresInstance type that bundles subnets, security groups, IAM roles, and a managed database service into a single object, then expose that as a self-service abstraction for application teams.
Crossplane makes this possible through composite resource definitions, which let you define a desired state that spans many underlying services, while keeping a single resource in the Kubernetes API as the point of interaction.
The important property is the control loop.
Crossplane adopts the Kubernetes pattern of continuous reconciliation. Once a desired state is defined in custom resources, the Crossplane controllers continuously compare actual state in the cloud providers against the desired state in the cluster.
If anything drifts, Crossplane attempts to bring the external resources back into alignment. This means the Kubernetes cluster effectively becomes the central state management system for infrastructure provisioning and ongoing management.
For teams already standardising on Kubernetes clusters as a platform, Crossplane offers a Kubernetes-native way to manage infrastructure resources, integrate with existing RBAC, and provide fine-grained control and self-service to internal users without exposing them to individual cloud consoles.
What is Terraform?
Terraform is HashiCorp's infrastructure-as-code tool. It lets you define cloud resources and other infrastructure in human-readable, declarative configuration files written in Hashicorp configuration language (HCL), then uses Terraform core to build an execution plan and apply those changes to multiple cloud providers and services.
Terraform configuration files describe infrastructure provisioning in terms of resources, data sources, and modules. You manage resources such as virtual machines, storage, networking, and higher-level cloud services across multiple cloud providers, with a Terraform provider for each cloud or external API you target.
Instead of clicking through consoles, you treat infrastructure as code, storing it in Git, reviewing it like any other code, and letting Terraform translate a desired state into actions on the underlying APIs.
A basic Terraform workflow involves writing Terraform configurations, running terraform plan to see the difference between the current state file and the desired state, then running terraform apply to create or update resources. The state file tracks mappings between Terraform resources and real cloud resources. Meanwhile, state management, including remote backends, locking, and drift detection, becomes a central operational concern.
Because Terraform has existed for many years and is actively maintained with a large provider ecosystem, it's a mature tool that fits a wide range of IaC use cases. Many teams rely on it as the backbone of cloud infrastructure provisioning, from greenfield deployments to large multi-account, multi-region, multi-cloud environments.
A minimal Terraform snippet that provisions a resource might look like this:
resource "aws_s3_bucket" "logs" {
bucket = "my-project-logs"
acl = "private"
tags = {
project = "my-project"
env = "production"
}
}
This illustrates the declarative language style. You define the desired state of the bucket and Terraform figures out which API calls are required to create or update it, based on what is already recorded in the state file.
Crossplane vs. Terraform comparison: the key differences
At a high level, Crossplane and Terraform both implement infrastructure as code, yet they sit in different places in your architecture and use very different models to manage resources and state.
From an operational perspective, Crossplane behaves more like a programmable infrastructure management layer over your cloud infrastructure. You define custom resources, Crossplane makes sure the world matches the desired state defined in those resources, continuously watching for drift between actual state and desired state.
Terraform behaves more like a compiler and executor. You write code, you run commands, Terraform computes a plan by comparing Terraform configurations and the state file with what exists in the cloud, and you decide when to apply that plan. This provides very fine-grained control over when changes occur, which is attractive for regulated environments and organisations that need strict approval processes.
Here's a table summarising the most important differences.
| Category | Crossplane | Terraform |
|---|---|---|
| Primary model | Kubernetes-based control plane where infrastructure is represented as Kubernetes custom resources and reconciled continuously. | A standalone IaC tool that reads Terraform configuration files and applies changes through explicit plan and apply steps. |
| Where it runs | Always runs inside a Kubernetes cluster, using the Kubernetes API and controllers. | Runs as a CLI or in CI, independent of Kubernetes or any other orchestrator. |
| Resource representation | Infrastructure resources and external resources are modeled as custom resources and composite resources inside the cluster. | Infrastructure resources are modeled as HCL resources in .tf files, often grouped into modules and root modules. |
| State management | Uses the Kubernetes control plane and etcd as the de facto state store, with continuous reconciliation between desired state and actual state. | Uses an explicit state file managed by Terraform Core, often stored in remote backends such as S3, and relies on drift detection and explicit runs to reconcile. |
| Reconciliation model | Continuous reconciliation: controllers watch resources and bring actual state back to desired state automatically. | Explicit reconciliation: users or automations run terraform plan and terraform apply to move from one state to another. |
| Abstractions | Strong support for platform APIs and self-service abstractions through composite resource definitions and Crossplane providers. | Strong support for reusable modules, variables, and outputs, so teams can share Terraform code across many projects and environments. |
| Dependencies | Uses Kubernetes-style references and owner relationships between custom resources. | Builds a dependency graph from references between resources and data sources in Terraform configurations. |
| Integrations | Naturally integrated with Kubernetes RBAC, admission controllers, and GitOps tools that apply manifests. | Naturally integrated with Git-based workflows, CI, and tools like Terrateam that orchestrate terraform plan and terraform apply against many environments. |
| Learning curve | Requires familiarity with Kubernetes concepts, control planes, and custom resources. | Requires learning HCL and the terraform workflow, but does not require Kubernetes knowledge. |
| Typical use cases | Internal platform APIs, self-service for application teams, multi-cloud control planes for cloud services. | Broad infrastructure provisioning and management across clouds, data centers, and services, often as the default IaC tool in mixed environments. |
How state and reconciliation differ in practice
State management is one of the most practical differences in the Terraform vs. Crossplane debate. With Terraform, you usually configure remote backends so that teams share a central state management system, often backed by S3, GCS, or another blob store. You then use Terrateam or another automation layer to make sure every terraform plan and terraform apply happens in CI, with governance and approvals around each change.
With Crossplane, you do not see a separate state file. The Kubernetes cluster watches the desired state and applies it continuously, and drift detection is part of the control plane itself. Losing the cluster is therefore far more serious, because the entire desired state and actual state mapping for your infrastructure resources lives inside it.
Continuous reconciliation is powerful when you want infrastructure to remain in sync automatically, especially for short-lived infrastructure or infrastructure that must adapt to frequent changes. It can be time-consuming to design the custom resources and compositions that capture all the right behaviours, and you must think about how these choices interact with the rest of your Kubernetes clusters.
Explicit plan and apply cycles are more natural when you want concrete review steps, when you care about each change going through a Terraform plan visible in a pull request, and when you prefer drift detection to be a scheduled activity instead of a constantly running loop.
This is where tools like Terrateam and its drift detection use cases become relevant, because they layer automated checks, notifications, and workflows on top of the basic Terraform engine. Get in touch to book a Terrateam demo today.
When you should use Crossplane versus Terraform
The right choice between Crossplane and Terraform depends less on which one is a better IaC tool and more on which one aligns with how you build and operate systems.
When to choose Crossplane
You're more likely to choose Crossplane when you already treat Kubernetes as the natural place to represent all infrastructure, when you want a control plane that can manage external resources by reconciling Kubernetes custom resources, and when platform engineering teams are ready to design self-service abstractions.
Crossplane makes it easier to expose a simple custom resource to application teams (for example, a PostgresDatabase object) and hide the complexity of individual resources such as networks, IAM roles, and encryption settings. It is particularly well-suited to organisations that build internal platforms to manage resources across multiple cloud providers through a single Kubernetes cluster.
When to choose Terraform
Terraform is a better fit when you want a flexible, cloud-agnostic, mature tool that does not require Kubernetes at all, and when you prefer the explicit Terraform workflow of plan and apply.
It excels at infrastructure creation and ongoing management for cloud infrastructure in many environments, from a single cloud provider to multiple cloud providers and other APIs. Terraform configurations live in their own repositories, and you can orchestrate runs with Terrateam to integrate them with your CI systems and infrastructure governance controls, so you can follow the best practices for CI/CD pipelines.
In many organisations, Terraform is the default choice because developers already understand Git, code review, and pipelines, whereas the Kubernetes model of control planes and continuous reconciliation introduces a steeper learning curve for teams that do not live inside clusters every day.
When Terraform is combined with Terrateam, you get central state management, approvals, audit trails, and automation that help you scale infrastructure safely as demand grows and more projects come online.
Can you use Crossplane and Terraform together?
Crossplane and Terraform are not mutually exclusive. In fact, Terraform and Crossplane can complement each other when you design the boundaries carefully.
One pattern is to use Terraform for foundational infrastructure provisioning, such as creating base networks, accounts, remote backends, and shared services, then to use Crossplane on top for application-facing infrastructure resources inside Kubernetes clusters.
Terraform manages resources that must exist before the cluster comes up, while Crossplane manages resources that are naturally tied to cluster lifecycles or that benefit from continuous reconciliation.
Another pattern is to treat Terraform as the source of truth for most infrastructure, but to deploy Crossplane as a specialised control plane in a small number of environments for specific self-service use cases.
You might provision Crossplane itself, its providers, and its configuration using Terraform code, then delegate parts of the organisation to use Crossplane custom resources for day-to-day infrastructure creation, while Terraform continues to own global infrastructure and core services.
With both options, Terrateam plays a coordinating role rather than competing directly. Terrateam orchestrates the Terraform workflow from GitHub, so it becomes the place where you define how and when terraform plan and terraform apply run, which remote state backends are in use, and how drift detection and infrastructure governance checks are enforced.
Crossplane continues to operate as a Kubernetes native control plane inside specific clusters, reconciling its own set of resources.
Seen from this angle, Crossplane vs. Terraform is less of a direct comparison and more of a choice about where you concentrate control.
Terrateam gives you a Git centric control plane for Terraform deployments, while Crossplane gives you a Kubernetes-centric control plane for external resources.
You can combine them when it makes sense, or lean heavily into one model depending on how your organisation prefers to manage environments and deployments.
Where Terrateam fits in a Crossplane vs. Terraform decision
When you standardise on Terraform as your primary IaC tool, Terrateam provides a higher-level control plane over Terraform Core, turning individual Terraform configurations into a coherent system for managing infrastructure across teams and environments. Instead of engineers running terraform plan on laptops, Terrateam runs it in CI as part of pull requests, records every plan and apply, and lets you express approvals, policies, and checks in one place.
This setup has several implications for infrastructure management. Terrateam helps you scale infrastructure because every project follows the same Terraform workflow, from writing code to merging changes, which means your infrastructure provisioning process is not reinvented for every team.
It gives you a central state management system through integration with remote backends, so you always know which state file is associated with which environment, and it simplifies drift detection by offering dedicated automated solutions that regularly check for divergence between desired and actual state.
It also improves infrastructure governance. Policies can:
- Prevent unreviewed changes
- Restrict who can manage resources in production
- Ensure that sensitive cloud resources are only modified through audited processes
Many teams attempt to approximate this kind of governance with homegrown tools and scripts, which are often fragile and time-consuming to maintain. By using Terrateam, you offload that logic into a purpose-built system that is actively maintained.
Terrateam removes many of Terraform's weaknesses by giving you a comprehensive but flexible way to manage Terraform-based infrastructure as code, with fine-grained control over when and how changes reach each environment.
Conclusion
Crossplane and Terraform both address different layers of infrastructure management.
Crossplane is a Kubernetes-based control plane that represents infrastructure as Kubernetes custom resources and relies on continuous reconciliation.
Terraform is a widely adopted IaC tool that uses a declarative language, HCL, to define resources, runs as a CLI or in CI, and manages state explicitly with a state file.
When you evaluate Crossplane and Terrateam, you are primarily choosing the core IaC engine and configuration language that will represent your infrastructure.
For many organisations, the pragmatic path is to keep Terraform as the main infrastructure as code tool, or to treat Crossplane as an optional control plane for specific platform engineering scenarios
Terraform users can then rely on Terrateam to orchestrate terraform plan and terraform apply across all projects, environments, and teams. This combination lets you use Terraform configurations to describe desired state and rely on Terrateam for automation, governance, and CI integration.
If you are ready to move beyond ad hoc scripts and manual terraform apply runs, and you want a system that helps you scale infrastructure, enforce infrastructure governance, and keep environments consistent without building your own control plane, you can sign up for Terrateam today to try it yourself.