Immutable Infrastructure

Build infrastructure that is replaced, never patched. Covers immutable server patterns, image-based deployments, golden images, blue-green infrastructure, and the patterns that eliminate configuration drift and snowflake servers.

Immutable infrastructure is a deployment strategy where infrastructure components are never modified in place. Instead, when changes are required, new instances are created with updated configurations or images, and old instances are decommissioned. This approach is essential when you need to ensure consistent, reproducible deployments across environments, especially during rollbacks, scaling, or configuration drift prevention.

Creating and Deploying Immutable Images

To create an immutable image, build a container image with all required dependencies, configuration, and binaries. For example, using Docker:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Build the image with a specific tag:

docker build -t myapp:v1.2.3 .

When deploying, always reference the exact image digest to avoid ambiguity:

docker run --name myapp-instance myapp@sha256:abc123...

If you deploy using a platform that supports immutable deployments, such as Kubernetes, specify the full image digest in your deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp@sha256:abc123...

Rolling Out Changes

When rolling out changes, create a new deployment with updated image tags or configuration. Never modify existing running instances directly.

For Kubernetes, use kubectl set image to update the deployment:

kubectl set image deployment/myapp-deployment myapp=myapp:v1.2.4

This command updates the deployment spec and triggers a rolling update. The old pods are terminated gradually while new ones are created.

If you're using a tool like kubectl rollout, check status with:

kubectl rollout status deployment/myapp-deployment

Failure to use full image digests can silently cause deployments to use unexpected images. A tag like latest may resolve to different images across environments, undermining immutability.

Managing Configuration Updates

Configuration changes should be bundled into new image builds or handled via external configuration management systems. Never modify running infrastructure state directly.

When using environment variables in containerized applications, pass them at runtime:

docker run -e DATABASE_URL=postgresql://... myapp:v1.2.3

In Kubernetes, use ConfigMaps:

apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  database_url: "postgresql://..."
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: myapp
        image: myapp:v1.2.3
        envFrom:
        - configMapRef:
            name: myapp-config

Handling Rollbacks

Rollbacks are achieved by deploying the previous immutable image version. Kubernetes supports rolling back to a previous revision:

kubectl rollout undo deployment/myapp-deployment --to-revision=1

This command reverts to the configuration state from revision 1.

If you're not using a declarative system like Kubernetes, create a tag or branch for each immutable release version:

git tag -a v1.2.3 -m "Release v1.2.3"

Managing Infrastructure State

Infrastructure should be described declaratively through configuration files and managed through automation tools. Changes are applied by creating new infrastructure rather than modifying existing resources.

For example, using Terraform to define a compute instance:

resource "aws_instance" "web" {
  ami           = "ami-12345678"
  instance_type = "t3.micro"
  tags = {
    Name = "web-server"
  }
}

Apply the configuration:

terraform apply

When changes are needed, update the Terraform configuration and reapply:

terraform apply

This creates a new instance with updated settings, leaving the old one in place until it's no longer needed.

Failure Modes and Silent Issues

Image Tag Ambiguity

Using tags like latest or stable instead of digests leads to silent failures. A deployment may appear successful but run a different image version than expected.

Partial Rollouts

In Kubernetes, if a rollout fails partway through, the system continues running with mixed versions until manually resolved.

Resource Cleanup Issues

If you delete an old instance before confirming the new one is healthy, it can lead to temporary outages or inconsistent states.

Validation and Verification

Before finalizing changes, validate that new instances are functioning correctly:

kubectl get pods -l app=myapp
kubectl describe pod myapp-pod-name

Check that all containers are running with expected image digests:

kubectl get pod myapp-pod-name -o jsonpath='{.spec.containers[*].image}'

Best Practices for Consistency

Always use exact image digests instead of tags when possible. Never modify infrastructure in place once it's deployed.

Use version control for all infrastructure definitions and configuration files. Changes should be reviewed through pull requests or change management processes.

Keep deployment artifacts immutable — a specific tag or digest should always map to the same set of binaries and configurations.

This page was rewritten on 15 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.