0
0
Terraformcloud~10 mins

Zero-downtime deployment pattern in Terraform - Commands & Configuration

Choose your learning style9 modes available
Introduction
When updating applications or infrastructure, downtime can disrupt users and cause loss of service. The zero downtime deployment pattern helps update resources smoothly without interrupting service, keeping everything running while changes happen.
When you want to update a web application without making users wait or see errors.
When deploying new versions of a service that must stay available 24/7.
When scaling infrastructure without stopping existing servers.
When migrating databases or backend services without downtime.
When rolling out security patches without interrupting user access.
Config File - main.tf
main.tf
provider "aws" {
  region = "us-east-1"
}

resource "aws_lb" "example" {
  name               = "example-lb"
  internal           = false
  load_balancer_type = "application"
  subnets            = ["subnet-12345678", "subnet-87654321"]
}

resource "aws_lb_target_group" "blue" {
  name     = "blue-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = "vpc-12345678"
}

resource "aws_lb_target_group" "green" {
  name     = "green-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = "vpc-12345678"
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.example.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.blue.arn
  }
}

resource "aws_ecs_service" "blue" {
  name            = "blue-service"
  cluster         = "example-cluster"
  task_definition = "blue-task-def"
  desired_count   = 2
  launch_type     = "FARGATE"
  network_configuration {
    subnets         = ["subnet-12345678", "subnet-87654321"]
    assign_public_ip = true
  }
  load_balancer {
    target_group_arn = aws_lb_target_group.blue.arn
    container_name   = "my-app"
    container_port   = 80
  }
  deployment_controller {
    type = "ECS"
  }
}

resource "aws_ecs_service" "green" {
  name            = "green-service"
  cluster         = "example-cluster"
  task_definition = "green-task-def"
  desired_count   = 0
  launch_type     = "FARGATE"
  network_configuration {
    subnets         = ["subnet-12345678", "subnet-87654321"]
    assign_public_ip = true
  }
  load_balancer {
    target_group_arn = aws_lb_target_group.green.arn
    container_name   = "my-app"
    container_port   = 80
  }
  deployment_controller {
    type = "ECS"
  }
}

This Terraform file creates an AWS Application Load Balancer with two target groups: blue and green. It defines two ECS services, blue and green, each attached to one target group. Initially, the blue service runs with two tasks, and the green service is stopped (desired count 0). This setup allows switching traffic between blue and green for zero downtime deployments by changing the load balancer listener's target group.

Commands
Initialize Terraform to download providers and prepare the working directory.
Terminal
terraform init
Expected OutputExpected
Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/aws... - Installing hashicorp/aws v4.60.0... - Installed hashicorp/aws v4.60.0 (signed by HashiCorp) Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure.
Apply the Terraform configuration to create the load balancer, target groups, and ECS services.
Terminal
terraform apply -auto-approve
Expected OutputExpected
aws_lb.example: Creating... aws_lb_target_group.blue: Creating... aws_lb_target_group.green: Creating... aws_lb.example: Creation complete after 10s [id=example-lb] aws_lb_target_group.blue: Creation complete after 5s [id=blue-target-group] aws_lb_target_group.green: Creation complete after 5s [id=green-target-group] aws_ecs_service.blue: Creating... aws_ecs_service.green: Creating... aws_ecs_service.blue: Creation complete after 15s [id=blue-service] aws_ecs_service.green: Creation complete after 15s [id=green-service] Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
-auto-approve - Skip manual approval to apply changes immediately
Check the current load balancer listener configuration to verify which target group receives traffic.
Terminal
terraform state show aws_lb_listener.http
Expected OutputExpected
id = arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/example-lb/50dc6c495c0c9188/6d0ecf831eec9f09 load_balancer_arn = arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/example-lb/50dc6c495c0c9188 port = 80 protocol = HTTP default_action { type = forward target_group_arn = arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/blue-target-group/6d0ecf831eec9f09 }
Update the load balancer listener to switch traffic from blue to green target group for zero downtime deployment.
Terminal
terraform apply -auto-approve -target=aws_lb_listener.http
Expected OutputExpected
aws_lb_listener.http: Modifying... [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/example-lb/50dc6c495c0c9188/6d0ecf831eec9f09] aws_lb_listener.http: Modifications complete after 5s [id=arn:aws:elasticloadbalancing:us-east-1:123456789012:listener/app/example-lb/50dc6c495c0c9188/6d0ecf831eec9f09] Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
-target - Apply changes only to the specified resource
-auto-approve - Skip manual approval
Key Concept

If you remember nothing else from this pattern, remember: switch traffic between identical environments to update without stopping service.

Common Mistakes
Updating the live service directly without using separate target groups.
This causes downtime because the service is unavailable during the update.
Use separate blue and green target groups and switch the load balancer listener to the updated group.
Not verifying the load balancer listener target group after deployment.
Traffic may still go to the old version, causing confusion and failed updates.
Always check the listener configuration to confirm traffic is routed to the intended target group.
Applying all changes at once without targeting the listener update.
This can cause unintended resource changes and longer deployment times.
Use targeted apply to update only the load balancer listener when switching traffic.
Summary
Initialize Terraform to prepare the environment with 'terraform init'.
Apply the infrastructure including load balancer, target groups, and ECS services with 'terraform apply'.
Verify which target group the load balancer listener is forwarding traffic to using 'terraform state show'.
Switch traffic between blue and green environments by updating the load balancer listener with targeted apply.