Choosing the Right Tool for the Job
Ephemeral environments require two categories of infrastructure: the long-lived foundation that everything runs on, and the short-lived application stack that gets created and destroyed per PR. Terraform and Helm are purpose-built for each of these categories respectively.
Terraform: The Foundation Layer
Terraform provisions cloud infrastructure — VPCs, Kubernetes clusters, load balancers, DNS zones, IAM roles. It is declarative and powerful, but it is not fast. Spinning up a new AWS EKS cluster or RDS instance can take 10–25 minutes. That is completely unacceptable for a PR preview workflow where developers expect feedback in under 5 minutes.
The correct role for Terraform is managing long-lived shared infrastructure that all ephemeral environments share:
- The Kubernetes cluster (EKS, GKE, or AKS)
- The wildcard DNS zone (
*.dev.mycompany.com) - The Ingress Controller (e.g., NGINX or Traefik) and its Load Balancer
- A wildcard TLS certificate
- Shared services like a container registry or secrets manager
This infrastructure is provisioned once and updated rarely. Terraform's slowness is irrelevant here because it is not in the hot path of PR creation.
Helm: The Ephemeral Application Layer
Helm is Kubernetes' package manager. It takes a templated set of Kubernetes manifests (called a chart) and renders them with specific values before applying them to the cluster. Deploying a Helm chart takes seconds, not minutes.
The correct role for Helm is deploying the application stack for each PR into its own isolated Kubernetes Namespace:
- The application's Deployment and Service
- An Ingress resource with a PR-specific hostname
- A lightweight in-cluster database (e.g., a Postgres container) for stateful apps
- Any supporting services (Redis, mock APIs, etc.)
The namespace acts as a logical boundary. Resources in ns-pr-123 cannot accidentally interfere with resources in ns-pr-124. When the PR closes, deleting the namespace deletes everything inside it in one operation.
Why not use Terraform for everything?
Some teams try to use Terraform workspaces to manage ephemeral environments. This works but has serious drawbacks: Terraform state files must be managed per workspace, plan/apply cycles are slow, and state locking can cause pipeline failures when multiple PRs open simultaneously. Helm with Kubernetes namespaces avoids all of these problems for the application layer.
A note on databases: For stateful resources like databases, use a containerized solution inside the namespace (e.g., a Postgres Pod with an ephemeral volume) rather than a cloud-managed database (e.g., AWS RDS). Cloud databases are slow to provision and expensive to run per-PR. The exception is when you are specifically testing database infrastructure changes — in that case, a real cloud database is required, but this should be rare and explicitly scoped.