
August 24, 2026
9 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
Self-service infrastructure with Crossplane solves the most persistent bottleneck in modern web development: engineers waiting days for DevOps to provision databases, buckets, or DNS records. Instead of filing tickets, your team declares infrastructure needs directly in Kubernetes manifests, treating cloud resources exactly like application deployments. This shift transforms infrastructure from a gatekept service into a scalable, auditable API surface that integrates natively with your existing CI/CD pipelines and GitOps workflows.
How does self-service infrastructure with Crossplane differ from Terraform?
The distinction between microservice architecture strategies and infrastructure tooling often blurs, but the operational model differs fundamentally. Terraform operates as an imperative pipeline tool: you write HCL, run terraform apply, and state is reconciled at execution time. Crossplane runs as a continuous control plane inside your Kubernetes cluster, constantly reconciling desired state against actual cloud state using the same reconciliation loop pattern familiar to any K8s operator.
In practice, this means Crossplane detects and corrects drift automatically. If someone manually modifies an RDS instance in the AWS console, Crossplane’s reconciliation loop will revert it to match the declared spec within minutes. Terraform won’t catch this until the next planned apply. For teams running production Laravel APIs or eCommerce platforms where configuration drift causes subtle bugs, this continuous enforcement is transformative.
| Criteria | Terraform | Crossplane |
|---|---|---|
| Execution Model | Imperative pipeline runs | Continuous K8s controller |
| Drift Detection | Only on plan/apply | Automatic reconciliation |
| State Storage | External backend (S3, Consul) | etcd (K8s native) |
| Abstraction Layer | Modules (HCL) | XRDs + Compositions (YAML) |
| RBAC Integration | Separate IAM policies | Native K8s RBAC |
| Multi-cloud | Provider plugins | Provider CRDs unified API |
| Learning Curve | HCL syntax | K8s CRD authoring |
What are Composite Resource Definitions and why do they matter?
Composite Resource Definitions (XRDs) are the abstraction layer that makes self-service infrastructure with Crossplane actually safe for developer consumption. Without XRDs, you’re just exposing raw cloud provider CRDs directly to application teams — which defeats the purpose entirely. An XRD defines a simplified, opinionated interface that hides provider-specific complexity while enforcing organizational standards.
Think of XRDs as the contract between your platform team and your application developers. The platform team encodes best practices, security requirements, and naming conventions into the composition. The developer sees only the fields relevant to their workload. On a recent legal-tech portal project, we defined a PostgreSQLInstance XRD that exposed only database name, storage size, and performance tier. Backup schedules, encryption settings, VPC placement, and parameter groups were all enforced by the composition — developers couldn’t accidentally create unencrypted public databases even if they tried.
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: postgresqlinstances.platform.example.com
spec:
group: platform.example.com
names:
kind: PostgreSQLInstance
plural: postgresqlinstances
claimNames:
kind: PostgreSQLClaim
plural: postgresqlclaims
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
dbName:
type: string
description: "Application database name"
storageGB:
type: integer
minimum: 20
maximum: 500
tier:
type: string
enum: [development, staging, production]
required: [dbName, tier] This XRD constrains input at the schema level. The tier enum prevents typos. Storage bounds prevent both under-provisioning and runaway costs. When a developer submits a claim against this XRD, Crossplane’s composition engine maps these simple fields to dozens of underlying AWS or GCP resource specifications. The developer never touches RDSInstance, SecurityGroup, or DBSubnetGroup CRDs directly.
The composition itself uses patch-and-transform or function pipelines to wire everything together. In 2026, function pipelines have largely replaced patch-and-transform for non-trivial compositions because they support conditional logic, iteration, and external data lookups without resorting to fragile nested patches. You write compositions in Go, Python, or TypeScript as containerized functions, giving you real programming language expressiveness instead of YAML templating gymnastics.
How do you implement safe self-service infrastructure with Crossplane guardrails?
Exposing infrastructure APIs without guardrails is how you get a Rs 800,000/month (~USD 6,000) surprise bill from orphaned GPU instances. Safety in self-service infrastructure with Crossplane requires defense in depth across four layers: schema validation, RBAC scoping, policy enforcement, and cost controls.
- Schema-level constraints: Use OpenAPI validation in your XRDs to enforce minimums, maximums, enums, and regex patterns. Never trust developers to pick appropriate instance sizes or storage tiers voluntarily. Encode your organization’s approved catalog directly in the schema.
- Namespace-scoped RBAC: Give each team or project its own namespace with RoleBindings that permit only specific claim types. A frontend team shouldn’t be able to provision VPCs or IAM roles. Use Kubernetes’ native RBAC rather than building custom admission webhooks when possible.
- OPA/Kyverno policies: Deploy Open Policy Agent or Kyverno as a secondary validation layer for rules that don’t fit cleanly in OpenAPI schemas. Examples include requiring specific tags for cost allocation, blocking certain regions, or enforcing encryption-at-rest on all storage resources. These policies evaluate claims before Crossplane processes them.
- Budget alerts and quotas: Configure cloud provider budget alerts independently of Crossplane. Crossplane doesn’t track spend. Set up AWS Budgets, GCP Billing Alerts, or Azure Cost Management to notify platform teams when projected spend exceeds thresholds. Consider integrating with tools like Kubecost for cluster-level attribution.
On production systems I’ve worked on, the combination of XRD schema constraints plus OPA policies caught roughly 90% of misconfiguration attempts before resources were ever provisioned. The remaining 10% were edge cases involving composition bugs — which is why testing compositions in isolated clusters before promoting to production is non-negotiable.
# Example Kyverno policy enforcing mandatory cost-allocation tags
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-cost-tags
spec:
validationFailureAction: Enforce
rules:
- name: check-tags
match:
any:
- resources:
kinds:
- PostgreSQLClaim
- RedisClaim
- S3BucketClaim
validate:
message: "All infrastructure claims must include team and project tags"
pattern:
metadata:
labels:
team: "?*"
project: "?*" This policy blocks any claim missing required labels. Combined with namespace RBAC, it ensures every provisioned resource is attributable to a specific team and project for chargeback or showback reporting. For Nepal-based clients operating on tighter budgets, this attribution is often more important than the technical capability itself.
What does a production Crossplane deployment architecture look like?
A common mistake is deploying Crossplane into the same cluster as your application workloads. Don’t do this. Crossplane manages infrastructure that your applications depend on; if the app cluster dies, you lose the ability to manage the infrastructure keeping it alive. Production deployments use a dedicated management cluster pattern.
The management cluster should be small (3 nodes, modest instance sizes) and boring. It runs Crossplane core, provider controllers, your compositions, and GitOps tooling. Nothing else. Application teams interact with it exclusively through Git pull requests that modify claim manifests. ArgoCD or Flux syncs those changes into the management cluster, triggering Crossplane reconciliation.
Workload clusters consume infrastructure through connection secrets that Crossplane writes automatically. When a developer creates a PostgreSQLClaim, Crossplane provisions the RDS instance, creates a Kubernetes Secret containing the connection string, and optionally propagates that secret to the target workload cluster using a secret store provider. Your Laravel application mounts the secret and connects — no manual credential distribution, no environment variable sprawl. For teams already practicing GitOps for CI/CD pipeline automation, this fits naturally into existing workflows.
When should you choose self-service infrastructure with Crossplane over alternatives?
Crossplane isn’t universally superior. It excels when your team already operates Kubernetes as a primary platform and wants infrastructure management to follow the same declarative, GitOps-driven patterns. It struggles when your team lacks K8s operational maturity or when infrastructure needs are simple enough that Terraform modules suffice.
Choose Crossplane when you need continuous drift correction, native K8s RBAC integration, multi-cloud abstraction through a single API, or tight coupling between application deployments and their infrastructure dependencies. Avoid it when your team is still learning Kubernetes basics, when you have fewer than three developers consuming infrastructure, or when your cloud footprint is single-provider and stable. The operational overhead of maintaining a management cluster, authoring compositions, and debugging provider controller issues is real — budget at least one engineer’s ongoing attention for platforms serving fewer than ten teams.
For Nepal-based organizations evaluating this technology, consider your team’s existing skill set honestly. If your developers are comfortable with kubectl, Helm, and GitOps workflows, Crossplane accelerates delivery significantly. If they’re primarily PHP/Laravel developers who touch infrastructure occasionally, Terraform with well-documented modules and a simple CI pipeline may deliver faster time-to-value. The best tool is the one your team can operate reliably at 2 AM during an outage, not the one with the most elegant architecture diagram.
Getting Started with Self-Service Infrastructure with Crossplane
Start small. Pick one resource type your developers request frequently — typically PostgreSQL, Redis, or object storage. Define an XRD with conservative defaults, write a single composition targeting your primary cloud provider, and deploy it in a test management cluster. Let two or three teams use it for non-production workloads for a month before expanding scope. Measure adoption friction, document gaps, and iterate on the abstraction before declaring victory. Self-service infrastructure with Crossplane succeeds through incremental trust-building, not big-bang platform launches. If you’re evaluating whether this approach fits your organization’s infrastructure maturity, reach out to discuss your specific context.

