Snap CD vs Crossplane
Crossplane and Snap CD both manage infrastructure, but they come at the problem from opposite directions. Crossplane replaces Terraform with a Kubernetes-native control plane. Snap CD orchestrates your existing Terraform code. Understanding this distinction is key to choosing the right tool — or deciding that both have a place in your stack.
What Crossplane is
Crossplane is an open-source, CNCF-graduated project that extends Kubernetes to manage infrastructure. You define cloud resources as Kubernetes custom resources — VPCs, databases, DNS zones — and Crossplane controllers reconcile them against cloud provider APIs, the same way Kubernetes reconciles Pods against the container runtime.
The key building blocks:
- Managed Resources — individual infrastructure objects (an S3 bucket, an Azure SQL database) represented as Kubernetes CRDs.
- Compositions — templates that combine multiple managed resources into higher-level abstractions (e.g. "a database" that creates an RDS instance, a subnet group, and a security group).
- XRDs (Composite Resource Definitions) — the schema for those abstractions, defining what inputs the consumer provides.
- Providers — plugins that know how to talk to specific cloud APIs (provider-aws, provider-azure, provider-gcp).
The paradigm difference
This is the most important distinction to understand.
Crossplane replaces Terraform. You stop writing HCL. Your infrastructure is defined in YAML manifests, stored in etcd, and managed by Kubernetes controllers. The reconciliation loop is continuous — there's no plan or apply, just desired state that the controllers converge toward.
Snap CD orchestrates Terraform. Your HCL code stays exactly as it is. Snap CD adds the layer above: when to run it, what inputs to provide, who approves it, and how outputs flow between modules. Your Terraform code has no Snap CD-specific constructs.
This means adopting Crossplane is a rewrite. Adopting Snap CD is additive.
State model
Crossplane stores all state in the Kubernetes API server, which ultimately means etcd. Every managed resource is a Kubernetes object with a status subresource that tracks the real-world state.
This has operational implications:
- etcd size limits. Large infrastructures can push etcd toward its default 2 GB database size limit. You can raise it, but you're now in the business of capacity-planning your control plane's backing store. At scale, the sheer number of CRDs registered by Crossplane providers can make the API server unresponsive.
- Backup and restore. Infrastructure state recovery means etcd snapshot recovery. If you lose the cluster without a backup, you lose your record of what exists in the cloud.
- State inspection. You use
kubectl getandkubectl describeinstead ofterraform state listandterraform state show. Different tooling, different mental model.
Terraform stores state in remote backends you already know — S3, Azure Blob, GCS, Terraform Cloud. The operational properties of these backends are well understood, and the state file format is stable and inspectable.
Reconciliation vs plan/apply
This is where the tools diverge most sharply in day-to-day operation.
Crossplane reconciles continuously. When you change a manifest, the controller detects the drift and converges the real-world resource to match. There's no human-in-the-loop step. This is the Kubernetes model: declare what you want, the system makes it so.
For application deployments, continuous reconciliation is usually fine. For infrastructure, many teams consider it dangerous. A typo in a VPC CIDR block takes effect immediately. There's no plan output to review, no approval gate to pass, no "are you sure?" before the controller modifies your production network. A dry-run / preview capability has been requested for over four years and remains unresolved.
Snap CD preserves Terraform's plan-then-approve workflow:
- A change is detected (new commit, dependency output change, configuration update).
- A Runner executes
terraform plan. - The plan is presented for review.
- If approval thresholds are met, the Runner executes
terraform apply.
The human stays in the loop. For infrastructure where a bad change can take down production, this is often non-negotiable.
Provider ecosystem
Crossplane has its own provider ecosystem, separate from Terraform's. The major cloud providers are covered (AWS, Azure, GCP), but resource coverage is narrower than Terraform's. Terraform has over 4,000 providers on the registry, covering everything from major clouds to niche SaaS APIs. If you need a Terraform provider for Cloudflare, Datadog, PagerDuty, or your internal platform, it almost certainly exists.
Crossplane providers are improving, and the Upjet project generates Crossplane providers from Terraform provider schemas, which has closed the gap significantly. But "generated from Terraform" and "battle-tested in production" are different things. If your infrastructure uses providers outside the big three clouds, check coverage before committing.
Snap CD uses Terraform's full provider ecosystem directly. If terraform apply can manage it, Snap CD can orchestrate it.
Composition vs modules
Crossplane Compositions let platform teams build self-service abstractions:
apiVersion: database.example.com/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-database
spec:
parameters:
storageGB: 50
version: "15"
Behind this simple interface, a Composition might create an RDS instance, a subnet group, a parameter group, security group rules, and a DNS record. The consumer doesn't see the complexity.
This is powerful for platform engineering — building an internal developer platform where application teams request infrastructure through simplified APIs.
Snap CD's Modules are different. Each Module is an independent Terraform root module with its own state. Modules are wired together via snapcd_module_input_from_output, forming a dependency graph. There's no abstraction layer hiding the underlying resources — each module is standard Terraform that anyone can read and run independently.
Compositions also lack explicit dependency ordering between the resources they create — resources reconcile in parallel with no way to express "create A before B", and deletion ordering is similarly fragile.
These serve different use cases. Crossplane Compositions are for hiding complexity behind a clean API. Snap CD Modules are for decomposing a large infrastructure into independently deployable units with managed dependencies.
Learning curve
Crossplane requires:
- Kubernetes expertise — you need a cluster to run it, and you need to understand the controller model.
- XRDs and Compositions — a new abstraction layer with its own patterns and pitfalls.
- ProviderConfigs — how Crossplane authenticates to cloud APIs.
- The reconciliation mental model — understanding eventual consistency, status conditions, and why your resource is stuck in a
Creatingstate.
If your team already lives in Kubernetes, this may be a natural extension. If your team uses Kubernetes for workloads but manages infrastructure with Terraform, Crossplane adds a significant new surface area.
Snap CD requires Terraform knowledge — which the team likely already has, since you wouldn't be evaluating Snap CD otherwise. Configuration is done via the Terraform provider or the web UI. The concepts (Modules, Stacks, Namespaces, Runners) map to things Terraform users already understand.
Migration path
To Crossplane: you rewrite your infrastructure from HCL to YAML. Every resource block becomes a Kubernetes manifest. Every variable becomes a Composition input. Every output becomes a status field. State must be imported or resources recreated. This is a significant project — weeks to months for a non-trivial infrastructure.
To Snap CD: you keep your existing Terraform code. You define Modules that point to your Git repos, wire up dependencies, and configure Runners. Your first deployment can happen in hours because you're not changing the infrastructure code, just adding orchestration around it.
Access control
Crossplane uses Kubernetes RBAC. You control who can create, modify, or delete custom resources using standard Kubernetes Roles and ClusterRoles. This is familiar if you already manage Kubernetes access, but it operates at the Kubernetes API level — there's no concept of "can approve but not apply" or "can deploy to test but not prod" built into the infrastructure workflow.
Snap CD has purpose-built RBAC for infrastructure deployment: roles scoped to organisations, Stacks, Namespaces, Modules, and Runners. An engineer can be Contributor on the test stack but Reader on prod. A service principal can be Approver on staging. These roles apply uniformly across the web UI, API, and Terraform provider.
Comparison table
| Dimension | Crossplane | Snap CD |
|---|---|---|
| Paradigm | Replaces Terraform (YAML + controllers) | Orchestrates Terraform (HCL stays as-is) |
| State storage | Kubernetes API server (etcd) | Terraform remote backends (S3, Azure, GCS, etc.) |
| Change workflow | Continuous reconciliation (no plan step) | Plan → review → approve → apply |
| Provider coverage | Growing, Upjet-generated from Terraform schemas | Full Terraform provider ecosystem |
| Abstraction model | Compositions + XRDs (platform APIs) | Modules with dependency wiring |
| Prerequisites | Kubernetes cluster | Snap CD Server + Runner(s) |
| Migration effort | Rewrite from HCL to YAML | Additive — keep existing Terraform code |
| RBAC | Kubernetes RBAC | Purpose-built infrastructure RBAC |
| Approval gates | None built-in | Built-in with configurable thresholds |
| Drift handling | Continuous reconciliation | Scheduled drift detection with plan review |
| Audit trail | Kubernetes events + controller logs | Persistent server-side history |
| Learning curve | Kubernetes + XRDs + Compositions | Terraform (likely already known) |
When to choose which
Crossplane is a good fit when:
- You're building an internal developer platform and want application teams to provision infrastructure through simplified Kubernetes-native APIs.
- Your team is deeply invested in the Kubernetes ecosystem and wants infrastructure to follow the same reconciliation model as workloads.
- You're starting fresh or willing to rewrite existing infrastructure definitions.
- Continuous reconciliation (no plan/approve step) is acceptable for your risk profile.
Snap CD is a good fit when:
- You have existing Terraform code that works and you want to add orchestration, not rewrite it.
- You need plan-then-approve workflows with human review before changes hit production.
- Your infrastructure uses Terraform providers that Crossplane doesn't cover.
- You want granular approval gates and RBAC without building them on top of Kubernetes primitives.
- You need cross-state dependency management with automatic cascading re-plans.
Using both? It's possible in theory — Crossplane managing lower-level platform resources while Snap CD orchestrates higher-level application infrastructure via Terraform. In practice, running two infrastructure management paradigms adds complexity. Most teams are better served picking one approach and committing to it.
See also
- Modular Deployments — how Snap CD's Module system wires cross-state dependencies
- Non-invasive Orchestration — Snap CD runs standard Terraform commands, no wrappers or rewrites
- Self-Hosted Terraform Runners with Credential Isolation — how Runners provide per-environment credential isolation
- A Permission System Built for Infrastructure — purpose-built RBAC for infrastructure workflows