AWS Terraform Blue-Green Deployment Using Elastic Beanstalk
Architectural Diagram

Blue - Green Deployment Strategy
Blue-green deployment is a release technique that keeps two identical production environments - nicknamed “blue” and “green.”
At any moment, only ONE of them is live and serving real users. Say the “blue“.
To deploy a new version, you:
Push the new build to the idle environment (say green).
Run whatever tests you need against green.
Once green is healthy, switch the router / load-balancer / Elastic-Beanstalk URL so that all incoming traffic instantly goes to green instead of blue.
If something breaks, you “flip back” to blue in seconds.
If everything looks good, leave green as the new live environment and recycle blue for the next release.
For this project, we will use two applications and deploy them to production. Then, after that, we will swap the production from blue to green.
Blue Environment Setup
We set up the Blue environment with version 1.0 in AWS Elastic Beanstalk.
1. Uploads the app code to S3
resource "aws_s3_object" "app_v1" {
bucket = aws_s3_bucket.app_versions.id
key = "app-v1.zip"
source = "${path.module}/app-v1/app-v1.zip"
etag = filemd5("${path.module}/app-v1/app-v1.zip")
tags = var.tags
}
Takes
app-v1.zipfrom your local folderUploads it to an S3 bucket (named
app_versions)Calculates MD5 hash to detect changes
2. Creates an Elastic Beanstalk app version
resource "aws_elastic_beanstalk_application_version" "v1" {
name = "${var.app_name}-v1"
application = aws_elastic_beanstalk_application.app.name
description = "Application Version 1.0 - Initial Release"
bucket = aws_s3_bucket.app_versions.id
key = aws_s3_object.app_v1.id
tags = var.tags
}
Registers
app-v1.zipas versionyour-app-name-v1Links it to your main EB application
Stores it in S3 with the version label
3. Launches the production environment (Blue)
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
tier = "WebServer"
version_label = aws_elastic_beanstalk_application_version.v1.name
# IAM Settings
setting {
....
}
Creates an environment called
your-app-name-blueDeploys version 1.0 to it
Uses your specified platform (
solution_stack_name)Sets it as a WebServer tier (production-ready)
In simple terms: It bundles the app → uploads to S3 → registers as EB version 1.0 → deploys to production (blue environment).
Green Environment Setup
The same sequence of measures for the green environment as well.
# Application Version 2.0 (Green Environment - Staging)
resource "aws_s3_object" "app_v2" {
bucket = aws_s3_bucket.app_versions.id
key = "app-v2.zip"
source = "${path.module}/app-v2/app-v2.zip"
etag = filemd5("${path.module}/app-v2/app-v2.zip")
tags = var.tags
}
resource "aws_elastic_beanstalk_application_version" "v2" {
name = "${var.app_name}-v2"
application = aws_elastic_beanstalk_application.app.name
description = "Application Version 2.0 - New Feature Release"
bucket = aws_s3_bucket.app_versions.id
key = aws_s3_object.app_v2.id
tags = var.tags
}
# Green Environment (Staging/Pre-production)
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
tier = "WebServer"
version_label = aws_elastic_beanstalk_application_version.v2.name
# IAM Settings
...
}
Main Terraform Configuration
We set up security and IAM permissions.
1. EC2 Instance Role (for your app servers)
# IAM Role for Elastic Beanstalk EC2 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"
}
}
]
})
tags = var.tags
}
Creates an IAM role
${your-app}-eb-ec2-roleAllows EC2 instances to "assume" this role
Gives your running app permissions to access AWS services (databases, S3, etc.)
2. Elastic Beanstalk Service Role (for AWS control plane)
# IAM Role for Elastic Beanstalk Service
resource "aws_iam_role" "eb_service_role" {
name = "${var.app_name}-eb-service-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "elasticbeanstalk.amazonaws.com"
}
}
]
})
tags = var.tags
}
Creates an IAM role
${your-app}-eb-service-roleAllows the Elastic Beanstalk service itself to manage your environments
AWS needs this to deploy, scale, and monitor your app
3. Locks down S3 bucket security
# Block public access to S3 bucket
resource "aws_s3_bucket_public_access_block" "app_versions" {
bucket = aws_s3_bucket.app_versions.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
Blocks all public access to your
app_versionsS3 bucketPrevents accidental public exposure of
app-v1.zipAll 4 public access settings = maximum security
Running
17-Blue-Green-Deployment git:(main) sudo chmod 755 package-apps.sh
[sudo] password for kutt:
17-Blue-Green-Deployment git:(main)
17-Blue-Green-Deployment git:(main) ./package-apps.sh
=====================================
Packaging Applications for Deployment
=====================================
Packaging Application v1.0 (Blue)...
[SUCCESS] Created app-v1/app-v1.zip
Packaging Application v2.0 (Green)...
[SUCCESS] Created app-v2/app-v2.zip
=====================================
[SUCCESS] All applications packaged successfully!
=====================================
Next steps:
1. Run: terraform init
2. Run: terraform plan
3. Run: terraform apply
After applying the Terraform Apply:
Blue is in production with version 1.0

Green in the staging environment with version 2.0

Here, we test the environment, making sure the edge cases are solved and make it ready for production.
Now, we swap:
(Due to the cache, the application weern’t updating very well. Open in a new browser, and we can see the swap is done.)

Repo link: Here
Video Reference:
Arigato!