TerraformPilot

Cloud Computing

Mutable vs Immutable Infrastructure: What's the Difference?

Mutable vs immutable infrastructure compared. Learn the differences, when to use each, and how tools like Terraform, Docker, and Ansible fit in.

LLuca Berton4 min read

Introduction

#

When you deploy a server, can you change it later — or do you throw it away and build a new one? That's the core question behind mutable vs immutable infrastructure.

Mutable: You deploy a server and modify it over time (patches, config changes, updates). Immutable: You deploy a server and never change it. Need an update? Build a new one, replace the old one.

Most modern infrastructure leans immutable, but both approaches have their place. Here's when to use each.

Quick Comparison

#
MutableImmutable
ChangesModify servers in placeReplace servers entirely
Config driftLikely over timeImpossible by design
RollbackComplex (undo changes)Simple (deploy previous version)
ToolsAnsible, Chef, Puppet, SSHTerraform, Docker, Packer, Kubernetes
Deploy speedFast (small changes)Fast (swap instances)
StateServers are uniqueServers are disposable
ScalingCopy server + apply scriptsLaunch from image
Best forLegacy systems, stateful serversMicroservices, cloud-native apps

Mutable Infrastructure

#

In mutable infrastructure, servers are updated in place after deployment. You SSH in, apply patches, change configurations, restart services.

How It Works

#
Day 1: Deploy Ubuntu 22.04 server
Day 30: apt update && apt upgrade (security patches)
Day 60: Change nginx config, restart nginx
Day 90: Install monitoring agent
Day 120: Update application to v2.0

The server accumulates changes over time. Each server becomes unique based on its history.

Real-World Example: Ansible

#

Ansible is the most popular mutable infrastructure tool. It connects to existing servers and applies changes:

# ansible playbook — modify servers in place
- hosts: webservers
  tasks:
    - name: Update packages
      apt:
        upgrade: dist
        update_cache: yes
 
    - name: Install nginx
      apt:
        name: nginx
        state: present
 
    - name: Deploy app config
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: restart nginx

The Configuration Drift Problem

#

The biggest risk with mutable infrastructure is configuration drift — servers that should be identical gradually become different:

Server A: Ubuntu 22.04, nginx 1.22, Node 18, monitoring agent v2
Server B: Ubuntu 22.04, nginx 1.24, Node 20, monitoring agent v3
Server C: Ubuntu 22.04, nginx 1.22, Node 18, no monitoring agent (someone forgot)

All three servers were supposed to be identical. Over months of manual patches and hotfixes, they diverged. Now a deployment that works on Server A fails on Server B. This is the "snowflake server" problem.

When Mutable Makes Sense

#
  • Stateful servers: Database servers that can't be easily replaced
  • Legacy applications: Apps that weren't designed for containerization
  • Quick hotfixes: Emergency patches that need to go out immediately
  • Small teams: When the overhead of building images isn't justified
  • Compliance: When you need to prove exactly what changed and when

Immutable Infrastructure

#

In immutable infrastructure, servers are never modified after deployment. Every change produces a new server image, and the old server is destroyed.

How It Works

#
v1.0: Build image → Deploy 3 instances → Running
v1.1: Build NEW image → Deploy 3 NEW instances → Destroy old instances
v1.2: Build NEW image → Deploy 3 NEW instances → Destroy old instances

No SSH, no patching, no config changes. If something needs to change, you build a new version from scratch.

Real-World Example: Terraform + Packer

#

Step 1: Build a machine image with Packer:

# packer template
source "amazon-ebs" "web" {
  ami_name      = "web-app-{{timestamp}}"
  instance_type = "t3.micro"
  region        = "us-east-1"
  source_ami    = "ami-0c55b159cbfafe1f0"
}
 
build {
  sources = ["source.amazon-ebs.web"]
 
  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y nginx nodejs",
      "sudo systemctl enable nginx"
    ]
  }
 
  provisioner "file" {
    source      = "app/"
    destination = "/var/www/app"
  }
}

Step 2: Deploy with Terraform:

# terraform — deploy the immutable image
resource "aws_instance" "web" {
  count         = 3
  ami           = "ami-NEW-VERSION"  # New AMI from Packer
  instance_type = "t3.micro"
 
  tags = {
    Name    = "web-${count.index}"
    Version = "1.1"
  }
}

Every deployment uses a fresh image. All servers are identical by construction.

Real-World Example: Docker + Kubernetes

#

Containers are the most common form of immutable infrastructure:

# Dockerfile — immutable by design
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
# kubernetes deployment — replace pods, never patch them
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 3
  template:
    spec:
      containers:
        - name: web
          image: myapp:1.1  # New version = new image
          ports:
            - containerPort: 3000

Why Immutable Wins for Most Use Cases

#
  1. No configuration drift: Every instance is built from the same image
  2. Easy rollback: Deploy the previous image version
  3. Reproducible: Same image works in dev, staging, and production
  4. Testable: Test the image before deploying to production
  5. Secure: No SSH access needed, smaller attack surface
  6. Auditable: Git history shows exactly what changed between versions

When Immutable Makes Sense

#
  • Stateless web services: API servers, web frontends
  • Microservices: Each service is its own image
  • Auto-scaling: Launch identical instances from an AMI
  • CI/CD pipelines: Build → Test → Deploy image
  • Cloud-native applications: Designed for containers/Kubernetes

Hybrid Approach: Immutable Compute, Mutable Data

#

Most real-world architectures use both:

┌─────────────────────────────────────────────┐
│  IMMUTABLE (replace, never modify)          │
│  • Web servers (Docker/AMI)                 │
│  • API servers                              │
│  • Worker processes                         │
│  • Lambda functions                         │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│  MUTABLE (update in place)                  │
│  • Databases (RDS, PostgreSQL)              │
│  • File storage (S3, EFS)                   │
│  • Message queues (SQS, RabbitMQ)           │
│  • Caches (Redis, ElastiCache)              │
└─────────────────────────────────────────────┘

Compute is immutable (easy to replace). Data is mutable (needs to persist). This is the standard pattern in modern cloud architecture.

Tool Mapping

#
ToolApproachWhat It Does
TerraformImmutableProvisions infrastructure (VMs, networks, services)
PackerImmutableBuilds machine images (AMIs, Docker images)
DockerImmutablePackages applications as container images
KubernetesImmutableOrchestrates container deployments
AnsibleMutableConfigures existing servers
ChefMutableConfigures existing servers
PuppetMutableConfigures existing servers

Terraform + Packer + Docker = fully immutable infrastructure pipeline.

Migration Path: Mutable → Immutable

#

If you're currently using mutable infrastructure:

  1. Start with containers: Dockerize one application
  2. Build CI/CD pipeline: Automate image builds
  3. Use Terraform: Manage infrastructure as code
  4. Adopt blue-green deploys: Run old and new versions simultaneously
  5. Remove SSH access: Once everything is automated, disable manual access
  6. Scale: Apply the pattern to more services

Hands-On Courses

#

Learn by doing with interactive courses on CopyPasteLearn:

Conclusion

#

Immutable infrastructure is the modern standard for cloud-native applications: build an image, test it, deploy it, never modify it. Mutable infrastructure still works for stateful systems and legacy applications. Most production environments use both — immutable compute (containers, AMIs) with mutable data (databases, storage). Start immutable with Terraform and Docker, use Ansible for the things that genuinely need in-place changes.

#DevOps#Infrastructure as Code#Cloud Computing#mutable infrastructure#immutable infrastructure

Share this article