IaC AWS

Terraform Module: AWS Elastic Beanstalk — opinionated, load-balanced web environments without the console clickops

Quick take — A reusable Terraform module for aws_elastic_beanstalk_environment that codifies platform versions, autoscaling, enhanced health, and rolling deploys so teams ship Elastic Beanstalk apps consistently. New here? Jump to the Quickstart below to deploy it in minutes; read on for how it works and when to reach for it.

Quickstart (copy-paste)

Minimal, runnable configuration — drop this in a .tf file and fill in the "..." placeholders (each required input is commented):

provider "aws" {
  region = "us-east-1"
}

module "elastic_beanstalk" {
  source = "git::https://dev.azure.com/teknohut/kloudvin/_git/terraform-modules//terraform-module-aws-elastic-beanstalk?ref=v1.0.0"

  application_name      = "..."           # Elastic Beanstalk application name (parent of all envir…
  solution_stack_name   = "..."           # Full 64bit solution stack string.
  vpc_id                = "..."           # VPC the environment launches into.
  instance_subnet_ids   = ["...", "..."]  # Subnets for the EC2 instances / ASG.
  instance_profile_name = "..."           # IAM instance profile attached to instances.
  service_role_arn      = "..."           # Beanstalk service role ARN (enhanced health, managed up…
}

Then terraform init && terraform apply. Every other input has a sensible default — see Inputs below to override behaviour.

What this module is

AWS Elastic Beanstalk is a managed orchestration layer that takes your application bundle — a JAR, a Docker image reference, a Node app, a .zip of PHP — and provisions the EC2 instances, Auto Scaling group, Elastic Load Balancer, security groups, and CloudWatch alarms needed to run it, while leaving you full access to those underlying resources. You hand it a platform (for example 64bit Amazon Linux 2023 v4.3.1 running Corretto 21) and a solution stack, and it manages the EC2 fleet, deploy strategy, and health reporting for you. It sits one rung below a full PaaS and one rung above raw EC2: more guardrails than rolling your own ASG, more escape hatches than App Runner or Fargate.

The catch is that almost everything meaningful about a Beanstalk environment is configured through option settings — hundreds of namespace / name / value triples spread across namespaces like aws:autoscaling:asg, aws:elasticbeanstalk:environment, aws:elbv2:listener, and aws:elasticbeanstalk:healthreporting:system. Configured by hand in the console, these drift constantly and are nearly impossible to review. This module wraps aws_elastic_beanstalk_environment (plus its parent aws_elastic_beanstalk_application and a versioned aws_elastic_beanstalk_application_version) and exposes the option settings that actually matter in production — instance type, scaling bounds, VPC placement, load balancer type, enhanced health, managed platform updates, and rolling deployment policy — as typed, validated variables. The result is a reviewable, repeatable environment definition instead of a screenshot of a console form.

When to use it

Module structure

terraform-module-aws-elastic-beanstalk/
├── versions.tf      # provider + Terraform version pins
├── main.tf          # application, application version, environment + option settings
├── variables.tf     # typed, validated inputs
└── outputs.tf       # ids, CNAME, endpoint URL, ASG/ELB attributes

versions.tf

terraform {
  required_version = ">= 1.5.0"

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

main.tf

locals {
  # Beanstalk environment names are 4-40 chars; many orgs encode app+env+region.
  environment_name = coalesce(var.environment_name, "${var.application_name}-${var.environment}")

  # Single instance vs LoadBalanced changes which namespaces apply.
  is_load_balanced = var.environment_type == "LoadBalanced"

  base_settings = [
    # --- VPC placement ---
    {
      namespace = "aws:ec2:vpc"
      name      = "VPCId"
      value     = var.vpc_id
    },
    {
      namespace = "aws:ec2:vpc"
      name      = "Subnets"
      value     = join(",", var.instance_subnet_ids)
    },
    {
      namespace = "aws:ec2:vpc"
      name      = "AssociatePublicIpAddress"
      value     = tostring(var.associate_public_ip_address)
    },

    # --- Launch / instance profile ---
    {
      namespace = "aws:autoscaling:launchconfiguration"
      name      = "IamInstanceProfile"
      value     = var.instance_profile_name
    },
    {
      namespace = "aws:autoscaling:launchconfiguration"
      name      = "InstanceType"
      value     = var.instance_type
    },
    {
      namespace = "aws:autoscaling:launchconfiguration"
      name      = "EC2KeyName"
      value     = var.ec2_key_name
    },
    {
      namespace = "aws:autoscaling:launchconfiguration"
      name      = "RootVolumeType"
      value     = "gp3"
    },

    # --- Environment type & service role ---
    {
      namespace = "aws:elasticbeanstalk:environment"
      name      = "EnvironmentType"
      value     = var.environment_type
    },
    {
      namespace = "aws:elasticbeanstalk:environment"
      name      = "ServiceRole"
      value     = var.service_role_arn
    },

    # --- Enhanced health reporting ---
    {
      namespace = "aws:elasticbeanstalk:healthreporting:system"
      name      = "SystemType"
      value     = var.enhanced_health ? "enhanced" : "basic"
    },

    # --- Managed platform updates ---
    {
      namespace = "aws:elasticbeanstalk:managedactions"
      name      = "ManagedActionsEnabled"
      value     = tostring(var.managed_updates_enabled)
    },
    {
      namespace = "aws:elasticbeanstalk:managedactions"
      name      = "PreferredStartTime"
      value     = var.managed_updates_start_time
    },
    {
      namespace = "aws:elasticbeanstalk:managedactions:platformupdate"
      name      = "UpdateLevel"
      value     = var.managed_updates_level
    },

    # --- Deployment policy (rolling / immutable / all-at-once) ---
    {
      namespace = "aws:elasticbeanstalk:command"
      name      = "DeploymentPolicy"
      value     = var.deployment_policy
    },
    {
      namespace = "aws:elasticbeanstalk:command"
      name      = "BatchSizeType"
      value     = "Percentage"
    },
    {
      namespace = "aws:elasticbeanstalk:command"
      name      = "BatchSize"
      value     = tostring(var.deployment_batch_size_percentage)
    },
  ]

  # Autoscaling + ELB settings only make sense for LoadBalanced environments.
  load_balanced_settings = local.is_load_balanced ? [
    {
      namespace = "aws:autoscaling:asg"
      name      = "MinSize"
      value     = tostring(var.min_instances)
    },
    {
      namespace = "aws:autoscaling:asg"
      name      = "MaxSize"
      value     = tostring(var.max_instances)
    },
    {
      namespace = "aws:elasticbeanstalk:environment"
      name      = "LoadBalancerType"
      value     = var.load_balancer_type
    },
    {
      namespace = "aws:ec2:vpc"
      name      = "ELBSubnets"
      value     = join(",", coalescelist(var.elb_subnet_ids, var.instance_subnet_ids))
    },
    {
      namespace = "aws:elbv2:loadbalancer"
      name      = "SecurityGroups"
      value     = join(",", var.elb_security_group_ids)
    },
    # Scale on average CPU.
    {
      namespace = "aws:autoscaling:trigger"
      name      = "MeasureName"
      value     = "CPUUtilization"
    },
    {
      namespace = "aws:autoscaling:trigger"
      name      = "Unit"
      value     = "Percent"
    },
    {
      namespace = "aws:autoscaling:trigger"
      name      = "UpperThreshold"
      value     = tostring(var.scale_up_cpu_threshold)
    },
    {
      namespace = "aws:autoscaling:trigger"
      name      = "LowerThreshold"
      value     = tostring(var.scale_down_cpu_threshold)
    },
  ] : []

  # Optional HTTPS listener on 443.
  https_settings = (local.is_load_balanced && var.https_certificate_arn != null) ? [
    {
      namespace = "aws:elbv2:listener:443"
      name      = "ListenerEnabled"
      value     = "true"
    },
    {
      namespace = "aws:elbv2:listener:443"
      name      = "Protocol"
      value     = "HTTPS"
    },
    {
      namespace = "aws:elbv2:listener:443"
      name      = "SSLCertificateArns"
      value     = var.https_certificate_arn
    },
    {
      namespace = "aws:elbv2:listener:443"
      name      = "SSLPolicy"
      value     = var.ssl_policy
    },
  ] : []

  # Application environment variables -> aws:elasticbeanstalk:application:environment
  app_env_settings = [
    for k, v in var.app_environment_variables : {
      namespace = "aws:elasticbeanstalk:application:environment"
      name      = k
      value     = v
    }
  ]

  all_settings = concat(
    local.base_settings,
    local.load_balanced_settings,
    local.https_settings,
    local.app_env_settings,
  )
}

resource "aws_elastic_beanstalk_application" "this" {
  name        = var.application_name
  description = var.application_description

  dynamic "appversion_lifecycle" {
    for_each = var.application_version_retention != null ? [1] : []
    content {
      service_role          = var.service_role_arn
      max_count             = var.application_version_retention
      delete_source_from_s3 = true
    }
  }

  tags = var.tags
}

# Bundle stored in S3 and promoted as an immutable, named version.
resource "aws_elastic_beanstalk_application_version" "this" {
  count = var.source_bundle_bucket != null && var.source_bundle_key != null ? 1 : 0

  name        = "${var.application_name}-${var.application_version_label}"
  application = aws_elastic_beanstalk_application.this.name
  description = "Version ${var.application_version_label}"
  bucket      = var.source_bundle_bucket
  key         = var.source_bundle_key

  tags = var.tags
}

resource "aws_elastic_beanstalk_environment" "this" {
  name                = local.environment_name
  application         = aws_elastic_beanstalk_application.this.name
  solution_stack_name = var.solution_stack_name
  tier                = var.tier
  cname_prefix        = var.cname_prefix
  version_label = try(aws_elastic_beanstalk_application_version.this[0].name, null)

  dynamic "setting" {
    for_each = local.all_settings
    content {
      namespace = setting.value.namespace
      name      = setting.value.name
      value     = setting.value.value
    }
  }

  tags = var.tags

  # The platform's managed updates may bump solution_stack_name out of band;
  # avoid perpetual diffs by ignoring drift on that attribute if desired.
  lifecycle {
    ignore_changes = [version_label]
  }
}

variables.tf

variable "application_name" {
  type        = string
  description = "Name of the Elastic Beanstalk application (parent of all environments)."

  validation {
    condition     = length(var.application_name) >= 1 && length(var.application_name) <= 100
    error_message = "application_name must be between 1 and 100 characters."
  }
}

variable "application_description" {
  type        = string
  description = "Human-readable description for the Beanstalk application."
  default     = "Managed by Terraform"
}

variable "environment" {
  type        = string
  description = "Logical environment suffix (e.g. dev, staging, prod) used to derive the environment name."
  default     = "dev"
}

variable "environment_name" {
  type        = string
  description = "Explicit Beanstalk environment name. If null, derived as <application_name>-<environment>."
  default     = null

  validation {
    condition     = var.environment_name == null || can(regex("^[a-zA-Z0-9][a-zA-Z0-9-]{2,38}[a-zA-Z0-9]$", var.environment_name))
    error_message = "environment_name must be 4-40 chars, alphanumeric and hyphens, not starting/ending with a hyphen."
  }
}

variable "solution_stack_name" {
  type        = string
  description = "Full Beanstalk solution stack, e.g. '64bit Amazon Linux 2023 v4.3.1 running Corretto 21'."

  validation {
    condition     = can(regex("^64bit ", var.solution_stack_name))
    error_message = "solution_stack_name should be a full 64bit solution stack string from `aws elasticbeanstalk list-available-solution-stacks`."
  }
}

variable "tier" {
  type        = string
  description = "Environment tier: 'WebServer' for HTTP apps or 'Worker' for SQS-backed background processing."
  default     = "WebServer"

  validation {
    condition     = contains(["WebServer", "Worker"], var.tier)
    error_message = "tier must be either 'WebServer' or 'Worker'."
  }
}

variable "environment_type" {
  type        = string
  description = "'LoadBalanced' (ALB/NLB + ASG) or 'SingleInstance' (one EC2, no LB)."
  default     = "LoadBalanced"

  validation {
    condition     = contains(["LoadBalanced", "SingleInstance"], var.environment_type)
    error_message = "environment_type must be 'LoadBalanced' or 'SingleInstance'."
  }
}

variable "cname_prefix" {
  type        = string
  description = "Optional CNAME prefix for the *.<region>.elasticbeanstalk.com endpoint. Null lets AWS generate one."
  default     = null
}

# --- Networking ---
variable "vpc_id" {
  type        = string
  description = "VPC the environment is launched into."
}

variable "instance_subnet_ids" {
  type        = list(string)
  description = "Subnets (typically private) for the EC2 instances / ASG."

  validation {
    condition     = length(var.instance_subnet_ids) > 0
    error_message = "At least one instance subnet is required."
  }
}

variable "elb_subnet_ids" {
  type        = list(string)
  description = "Subnets (typically public) for the load balancer. Defaults to instance_subnet_ids if empty."
  default     = []
}

variable "associate_public_ip_address" {
  type        = bool
  description = "Whether EC2 instances get public IPs. Keep false for private-subnet deployments."
  default     = false
}

# --- Compute / IAM ---
variable "instance_type" {
  type        = string
  description = "EC2 instance type for the environment's instances."
  default     = "t3.small"
}

variable "instance_profile_name" {
  type        = string
  description = "Name of the IAM instance profile attached to EC2 instances (e.g. aws-elasticbeanstalk-ec2-role)."
}

variable "service_role_arn" {
  type        = string
  description = "ARN of the Beanstalk service role used for enhanced health and managed updates."
}

variable "ec2_key_name" {
  type        = string
  description = "EC2 key pair name for SSH access. Empty string disables SSH key injection."
  default     = ""
}

# --- Autoscaling (LoadBalanced only) ---
variable "min_instances" {
  type        = number
  description = "Minimum size of the Auto Scaling group."
  default     = 2

  validation {
    condition     = var.min_instances >= 1
    error_message = "min_instances must be at least 1."
  }
}

variable "max_instances" {
  type        = number
  description = "Maximum size of the Auto Scaling group."
  default     = 4

  validation {
    condition     = var.max_instances >= 1
    error_message = "max_instances must be at least 1."
  }
}

variable "scale_up_cpu_threshold" {
  type        = number
  description = "Average CPU percent above which the ASG scales out."
  default     = 70
}

variable "scale_down_cpu_threshold" {
  type        = number
  description = "Average CPU percent below which the ASG scales in."
  default     = 30
}

variable "load_balancer_type" {
  type        = string
  description = "Load balancer type for LoadBalanced environments."
  default     = "application"

  validation {
    condition     = contains(["application", "network", "classic"], var.load_balancer_type)
    error_message = "load_balancer_type must be 'application', 'network', or 'classic'."
  }
}

variable "elb_security_group_ids" {
  type        = list(string)
  description = "Security groups attached to the load balancer (LoadBalanced only)."
  default     = []
}

# --- HTTPS listener ---
variable "https_certificate_arn" {
  type        = string
  description = "ACM certificate ARN. When set (and LoadBalanced), enables an HTTPS listener on 443."
  default     = null
}

variable "ssl_policy" {
  type        = string
  description = "TLS security policy for the HTTPS listener."
  default     = "ELBSecurityPolicy-TLS13-1-2-2021-06"
}

# --- Deployments ---
variable "deployment_policy" {
  type        = string
  description = "How new versions roll out: AllAtOnce, Rolling, RollingWithAdditionalBatch, or Immutable."
  default     = "Rolling"

  validation {
    condition     = contains(["AllAtOnce", "Rolling", "RollingWithAdditionalBatch", "Immutable"], var.deployment_policy)
    error_message = "deployment_policy must be AllAtOnce, Rolling, RollingWithAdditionalBatch, or Immutable."
  }
}

variable "deployment_batch_size_percentage" {
  type        = number
  description = "Percentage of instances updated per batch during a rolling deploy."
  default     = 50

  validation {
    condition     = var.deployment_batch_size_percentage > 0 && var.deployment_batch_size_percentage <= 100
    error_message = "deployment_batch_size_percentage must be between 1 and 100."
  }
}

# --- Health & managed updates ---
variable "enhanced_health" {
  type        = bool
  description = "Enable enhanced health reporting (requires a service role). Strongly recommended."
  default     = true
}

variable "managed_updates_enabled" {
  type        = bool
  description = "Enable Beanstalk managed platform updates in a maintenance window."
  default     = true
}

variable "managed_updates_start_time" {
  type        = string
  description = "Weekly maintenance window start, in 'Day:HH:MM' UTC format (e.g. 'Sun:03:00')."
  default     = "Sun:03:00"
}

variable "managed_updates_level" {
  type        = string
  description = "Highest update level applied automatically: 'minor' or 'patch'."
  default     = "minor"

  validation {
    condition     = contains(["minor", "patch"], var.managed_updates_level)
    error_message = "managed_updates_level must be 'minor' or 'patch'."
  }
}

# --- Application version / source bundle ---
variable "application_version_label" {
  type        = string
  description = "Version label appended to the application version name (e.g. a git SHA or semver)."
  default     = "initial"
}

variable "source_bundle_bucket" {
  type        = string
  description = "S3 bucket holding the deployable source bundle. Null skips creating an application version."
  default     = null
}

variable "source_bundle_key" {
  type        = string
  description = "S3 key of the deployable source bundle (zip/jar/war). Null skips creating an application version."
  default     = null
}

variable "application_version_retention" {
  type        = number
  description = "Max application versions to retain via lifecycle policy. Null disables the lifecycle rule."
  default     = 10
}

# --- App config ---
variable "app_environment_variables" {
  type        = map(string)
  description = "Key/value pairs injected as application environment variables."
  default     = {}
}

variable "tags" {
  type        = map(string)
  description = "Tags applied to the application, version, and environment."
  default     = {}
}

outputs.tf

output "application_name" {
  description = "Name of the Elastic Beanstalk application."
  value       = aws_elastic_beanstalk_application.this.name
}

output "environment_id" {
  description = "ID of the Elastic Beanstalk environment."
  value       = aws_elastic_beanstalk_environment.this.id
}

output "environment_name" {
  description = "Name of the Elastic Beanstalk environment."
  value       = aws_elastic_beanstalk_environment.this.name
}

output "cname" {
  description = "Fully qualified CNAME of the environment (the *.elasticbeanstalk.com hostname)."
  value       = aws_elastic_beanstalk_environment.this.cname
}

output "endpoint_url" {
  description = "Load balancer / instance endpoint URL for the environment."
  value       = aws_elastic_beanstalk_environment.this.endpoint_url
}

output "autoscaling_groups" {
  description = "Auto Scaling group names backing the environment."
  value       = aws_elastic_beanstalk_environment.this.autoscaling_groups
}

output "load_balancers" {
  description = "Load balancer names associated with the environment (empty for SingleInstance)."
  value       = aws_elastic_beanstalk_environment.this.load_balancers
}

output "instances" {
  description = "EC2 instance IDs currently running in the environment."
  value       = aws_elastic_beanstalk_environment.this.instances
}

output "application_version_label" {
  description = "The application version label deployed to the environment, if a source bundle was provided."
  value       = try(aws_elastic_beanstalk_application_version.this[0].name, null)
}

How to use it

module "elastic_beanstalk" {
  source = "git::https://dev.azure.com/teknohut/kloudvin/_git/terraform-modules//terraform-module-aws-elastic-beanstalk?ref=v1.0.0"

  application_name        = "orders-api"
  environment             = "prod"
  solution_stack_name     = "64bit Amazon Linux 2023 v4.3.1 running Corretto 21"
  environment_type        = "LoadBalanced"
  cname_prefix            = "orders-api-prod"

  # Networking
  vpc_id              = module.network.vpc_id
  instance_subnet_ids = module.network.private_subnet_ids
  elb_subnet_ids      = module.network.public_subnet_ids
  elb_security_group_ids = [aws_security_group.alb.id]

  # Compute / IAM
  instance_type         = "t3.medium"
  instance_profile_name = aws_iam_instance_profile.beanstalk_ec2.name
  service_role_arn      = aws_iam_role.beanstalk_service.arn

  # Autoscaling
  min_instances = 3
  max_instances = 8

  # Safe production rollout
  deployment_policy                = "Immutable"
  deployment_batch_size_percentage = 50
  enhanced_health                  = true

  # HTTPS
  https_certificate_arn = aws_acm_certificate.orders_api.arn

  # Deployable artifact built in CI and uploaded to S3
  source_bundle_bucket      = aws_s3_bucket.artifacts.id
  source_bundle_key         = "orders-api/${var.git_sha}.jar"
  application_version_label = var.git_sha

  app_environment_variables = {
    SPRING_PROFILES_ACTIVE = "prod"
    JAVA_TOOL_OPTIONS      = "-XX:MaxRAMPercentage=75"
    DB_HOST                = module.orders_db.endpoint
  }

  tags = {
    Team        = "payments"
    Environment = "prod"
    CostCenter  = "cc-4471"
  }
}

# Downstream: point a friendly Route 53 record at the environment's CNAME.
resource "aws_route53_record" "orders_api" {
  zone_id = aws_route53_zone.public.zone_id
  name    = "orders.example.com"
  type    = "CNAME"
  ttl     = 300
  records = [module.elastic_beanstalk.cname]
}

With Terragrunt

Terragrunt keeps this module DRY across environments — define the backend and provider once in a root config, then a thin terragrunt.hcl per environment supplies only the inputs that differ.

1. Root configlive/terragrunt.hcl (inherited by every module):

remote_state {
  backend = "s3"
  generate = { path = "backend.tf", if_exists = "overwrite" }
  config = {
    # ...s3 state bucket/container + key per path...
  }
}

2. Module configlive/prod/elastic_beanstalk/terragrunt.hcl:

include "root" {
  path = find_in_parent_folders()
}

terraform {
  source = "git::https://dev.azure.com/teknohut/kloudvin/_git/terraform-modules//terraform-module-aws-elastic-beanstalk?ref=v1.0.0"
}

inputs = {
  application_name = "..."
  solution_stack_name = "..."
  vpc_id = "..."
  instance_subnet_ids = ["...", "..."]
  instance_profile_name = "..."
  service_role_arn = "..."
}

3. Deploy one environment, or roll out all modules together:

cd live/prod/elastic_beanstalk && terragrunt apply        # this module
terragrunt run-all apply                      # every module under live/prod

Why Terragrunt here: the backend and provider live in one place instead of being copy-pasted into every module; inputs is overridden per environment (dev / stage / prod) without forking the module; and run-all orchestrates dependencies across modules. Reach for it once you have more than one environment or more than a handful of modules — for a single stack, the plain Quickstart above is enough.

Inputs

Name Type Default Required Description
application_name string yes Elastic Beanstalk application name (parent of all environments).
application_description string “Managed by Terraform” no Description for the application.
environment string “dev” no Logical env suffix used to derive the environment name.
environment_name string null no Explicit environment name; derived from app + environment if null.
solution_stack_name string yes Full 64bit solution stack string.
tier string “WebServer” no “WebServer” or “Worker”.
environment_type string “LoadBalanced” no “LoadBalanced” or “SingleInstance”.
cname_prefix string null no CNAME prefix for the elasticbeanstalk.com endpoint.
vpc_id string yes VPC the environment launches into.
instance_subnet_ids list(string) yes Subnets for the EC2 instances / ASG.
elb_subnet_ids list(string) [] no Subnets for the load balancer; falls back to instance subnets.
associate_public_ip_address bool false no Whether instances receive public IPs.
instance_type string “t3.small” no EC2 instance type.
instance_profile_name string yes IAM instance profile attached to instances.
service_role_arn string yes Beanstalk service role ARN (enhanced health, managed updates).
ec2_key_name string “” no EC2 key pair for SSH; empty disables.
min_instances number 2 no ASG minimum size.
max_instances number 4 no ASG maximum size.
scale_up_cpu_threshold number 70 no Average CPU percent to scale out.
scale_down_cpu_threshold number 30 no Average CPU percent to scale in.
load_balancer_type string “application” no “application”, “network”, or “classic”.
elb_security_group_ids list(string) [] no Security groups on the load balancer.
https_certificate_arn string null no ACM cert ARN; enables HTTPS listener on 443 when set.
ssl_policy string “ELBSecurityPolicy-TLS13-1-2-2021-06” no TLS policy for the HTTPS listener.
deployment_policy string “Rolling” no AllAtOnce, Rolling, RollingWithAdditionalBatch, or Immutable.
deployment_batch_size_percentage number 50 no Percent of instances updated per batch.
enhanced_health bool true no Enable enhanced health reporting.
managed_updates_enabled bool true no Enable managed platform updates.
managed_updates_start_time string “Sun:03:00” no Maintenance window start (Day:HH:MM UTC).
managed_updates_level string “minor” no “minor” or “patch” auto-update level.
application_version_label string “initial” no Version label appended to the application version name.
source_bundle_bucket string null no S3 bucket holding the source bundle.
source_bundle_key string null no S3 key of the source bundle.
application_version_retention number 10 no Max application versions retained; null disables lifecycle.
app_environment_variables map(string) {} no Environment variables injected into the app.
tags map(string) {} no Tags applied to all created resources.

Outputs

Name Description
application_name Name of the Elastic Beanstalk application.
environment_id ID of the environment.
environment_name Name of the environment.
cname Fully qualified CNAME hostname of the environment.
endpoint_url Load balancer / instance endpoint URL.
autoscaling_groups Auto Scaling group names backing the environment.
load_balancers Load balancer names (empty for SingleInstance).
instances EC2 instance IDs currently in the environment.
application_version_label Deployed application version label, if a bundle was provided.

Enterprise scenario

A payments platform runs a fleet of Spring Boot microservices and standardizes every one on this module so each service gets an identical orders-api-prod style environment: private-subnet instances behind an internet-facing ALB, an ACM-backed HTTPS listener, enhanced health wired to the service role, and managed platform updates pinned to a Sunday 03:00 UTC window. CI builds a JAR, uploads it to a versioned S3 artifact bucket, and passes the git SHA as application_version_label and source_bundle_key, so terraform apply promotes an immutable application version with a full audit trail and instant rollback to the prior label. Setting deployment_policy = "Immutable" means every release spins up a fresh batch of instances and only swaps traffic once they pass health checks, giving the payments team zero-downtime deploys without maintaining their own ECS pipeline.

Best practices

TerraformAWSElastic BeanstalkModuleIaC
Need this built for real?

Vinod is a Senior Cloud Architect (22+ yrs) — available for Azure / AWS / GCP architecture, landing zones, and migrations.

Work with me

Comments

Keep Reading