DEV Community

Cover image for Day 17 of #30DaysofAWSTerraform: Blue-Green Deployment with Elastic Beanstalk (The Hard Way)
Zakariyau Mukhtar
Zakariyau Mukhtar

Posted on

Day 17 of #30DaysofAWSTerraform: Blue-Green Deployment with Elastic Beanstalk (The Hard Way)

Day 17 was one of those days that really tested my patience but also deepened my understanding of real-world deployment strategies. Today, I learned about Blue-Green deployment, how Elastic Beanstalk fits into that strategy, and how to actually swap environments safely without downtime. It wasn’t smooth at all; IAM policies almost broke my spirit but the lesson stuck.

What Blue-Green Deployment Really Is:

Blue-Green deployment is a strategy where you maintain two identical environments:

  • Blue → current production (stable).
  • Green → new version (staging). Instead of deploying directly to production, you deploy the new version to the green environment, test it thoroughly, and then swap traffic instantly. If something goes wrong, rollback is just another swap away. This drastically reduces downtime and deployment risk something every serious production system needs.

Why Elastic Beanstalk?

Elastic Beanstalk abstracts a lot of infrastructure complexity while still giving control when needed. It manages:

  • EC2 instances.
  • Load balancers.
  • Auto Scaling.
  • Health checks.
  • Application versions.

For this demo, Elastic Beanstalk made Blue-Green deployment practical, especially when paired with Terraform for infrastructure consistency.

Terraform Setup: Providers and IAM (Where the Pain Started)

I started with provider configuration and IAM roles and this is where things got tough. Elastic Beanstalk requires multiple IAM roles, and incorrect attachments will break everything.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~>5.0"
    }
  }
  required_version = ">= 1.0"
}

provider "aws" {
  region = var.aws_region
}
Enter fullscreen mode Exit fullscreen mode

The EC2 role for Elastic Beanstalk instances:

resource "aws_iam_role" "eb_ec2_role" {
  name = "${var.app_name}-eb-ec2-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
    }]
  })
}
Enter fullscreen mode Exit fullscreen mode

Attaching the correct managed policies was critical and yes, I hit multiple errors here due to wrong role attachments.

Creating the Elastic Beanstalk Application:

Once IAM stopped fighting me, I defined the Elastic Beanstalk application itself:

resource "aws_elastic_beanstalk_application" "app" {
  name        = var.app_name
  description = "Blue-Green Deployment Demo Application"
}
Enter fullscreen mode Exit fullscreen mode

I also created an S3 bucket to store application versions each version mapped to either blue or green.

Blue Environment (Production):

The blue environment represents production running version 1.0:

resource "aws_elastic_beanstalk_environment" "blue" {
  name                = "${var.app_name}-blue"
  application         = aws_elastic_beanstalk_application.app.name
  solution_stack_name = var.solution_stack_name
  version_label       = aws_elastic_beanstalk_application_version.v1.name

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "Environment"
    value     = "blue"
  }
}
Enter fullscreen mode Exit fullscreen mode

This environment served stable traffic and stayed untouched while testing the new version.

Green Environment (Staging):

The green environment hosted version 2.0 with new features:

resource "aws_elastic_beanstalk_environment" "green" {
  name                = "${var.app_name}-green"
  application         = aws_elastic_beanstalk_application.app.name
  solution_stack_name = var.solution_stack_name
  version_label       = aws_elastic_beanstalk_application_version.v2.name

  setting {
    namespace = "aws:elasticbeanstalk:application:environment"
    name      = "Environment"
    value     = "green"
  }
}
Enter fullscreen mode Exit fullscreen mode

Both environments were load-balanced, scalable, and completely independent.

Swapping Blue and Green (The Cool Part):

After testing the green environment, I used a swap script to redirect traffic instantly:

aws elasticbeanstalk swap-environment-cnames \
  --source-environment-name "$BLUE_ENV" \
  --destination-environment-name "$GREEN_ENV" \
  --region "$REGION"
Enter fullscreen mode Exit fullscreen mode

This swap takes 1–2 minutes, with near-zero downtime. Production traffic moves to green, and blue becomes the fallback.

Commands Used:

Throughout this setup, I relied on the basics:

  • terraform init.
  • terraform plan.
  • terraform apply --auto-approve.
  • terraform destroy --auto-approve.

Simple commands complex consequences.

Final Thoughts

Today was tough. IAM policies and attachments caused multiple failures, and Elastic Beanstalk doesn’t forgive mistakes. But that’s exactly why this day mattered. I didn’t just learn Blue-Green deployment in theory I felt it.

Day 17 reminded me that real DevOps is messy, but the payoff is systems that deploy safely, scale reliably, and recover fast.

On to Day 18 🚀

Top comments (0)