Infrastructure Without IaC Is a Liability

When a developer requests a PostgreSQL database, someone on the ops team often handles it by logging into the cloud console, clicking through a wizard, picking a few settings, and sending back the connection string. This works in the moment. But the problems surface when the next person requests the same thing and receives subtly different settings, or when the original database needs to be recreated and nobody remembers how it was configured.

IaC makes infrastructure declarative, versioned, and repeatable. For platform teams, this is not a matter of preference. It is the foundation that makes self-service possible in the first place.

The Abstraction Layer

Does this mean developers should write IaC directly? Not quite. If developers end up writing Terraform or Crossplane themselves, the purpose of having a platform is defeated entirely. What the platform team needs to build is an abstraction layer โ€” a structure where developers declare what they need, and the platform handles how it gets implemented.

Developer request:          Platform translates to:
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ "I need a       โ”‚  โ”€โ”€โ†’   โ”‚ - RDS instance (db.t3.medium) โ”‚
โ”‚  PostgreSQL DB, โ”‚        โ”‚ - Security group              โ”‚
โ”‚  50GB, staging" โ”‚        โ”‚ - Subnet placement            โ”‚
โ”‚                 โ”‚        โ”‚ - Backup policy (daily)       โ”‚
โ”‚                 โ”‚        โ”‚ - Monitoring alerts            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

In this structure, the developer doesn't need to know about security groups or subnet placement, because the platform encodes those decisions internally. Exposing a simple interface to the developer while encapsulating complex infrastructure decisions inside the platform โ€” that is the core purpose of the abstraction layer.

Terraform vs Pulumi vs Crossplane

TerraformPulumiCrossplane
LanguageHCL (declarative)Python, TypeScript, Go, etc.YAML (Kubernetes CRDs)
StateState file (remote backend)State file (Pulumi Cloud or self-hosted)Kubernetes etcd
ReconciliationRun on apply onlyRun on apply onlyContinuous (controller loop)
Best forGeneral-purpose IaCTeams that prefer real codeKubernetes-native platforms
Platform fitModules as abstractionsComponents as abstractionsCompositions as abstractions
Learning curveLow-mediumDepends on languageMedium-high

There is no single correct answer among these three tools. Terraform is the most widely used starting point, with the broadest ecosystem. Crossplane excels in environments that are already Kubernetes-centric. Pulumi is an attractive option for teams that would rather not learn a separate domain-specific language.

Crossplane: Kubernetes-Native IaC

The reason Crossplane has gained attention is that it allows infrastructure provisioning to be handled in the same way as Kubernetes resources. If developers already know kubectl apply, they can use the same workflow to provision cloud resources as well โ€” effectively extending a familiar interface to cover infrastructure.

# Developer submits this
apiVersion: database.platform.io/v1alpha1
kind: PostgreSQL
metadata:
  name: orders-db
spec:
  size: medium
  storage: 50Gi
  environment: staging

Behind this simple manifest, a Crossplane Composition expands the request into actual cloud resources. An RDS instance, security group, and parameter group are created automatically, but the developer never has to deal with that complexity directly. They simply receive their database.

Self-Service Flow

To understand how self-service actually works in practice, consider the following sequence. First, the developer selects a resource from a catalog, which may be accessed through a UI, CLI, or YAML file. The request is then validated against the platform's policies โ€” size limits, naming conventions, and allowed regions are checked at this stage. Once validated, the IaC engine provisions the resource, and connection details are delivered back to the developer as secrets and endpoints. The provisioned resource then becomes trackable in the developer portal.

Through this process, the developer receives a database within minutes, while the platform team gains consistency, compliance, and an audit trail without any additional manual effort.

The Real Difference

A platform without IaC is ultimately just a ticketing system with an extra step. With IaC, true self-service becomes possible. Developers get what they need in minutes, and every resource remains consistent, auditable, and reproducible.

In the end, the presence of an abstraction layer is what separates "we use Terraform" from "we have a platform."

In the next post, we look at developer portals โ€” the front door where developers find services, documentation, and tools all in one place.