Back to Blog

Elastic Beanstalk Cluster Mode: First Look at the EKS-Backed Deployment Type

•
Tobias Schmidt
by Tobias Schmidt
Elastic Beanstalk Cluster Mode: First Look at the EKS-Backed Deployment Type

Elastic Beanstalk shipped its biggest change in years on September 17, 2026. Cluster Mode is a second way to run an application on Beanstalk, and it does not look like the Beanstalk you know. Instead of one EC2 environment per application, your app runs as a pod on a shared EKS cluster that Elastic Beanstalk creates and owns.

I have a rule for picking AWS services: build on the primitives, not on the convenience layers wrapped around them. I wrote it down in Build on ECS Primitives, Not Convenience Layers, after watching most of the layers AWS built on top of ECS die. Elastic Beanstalk has always sat on the convenience-layer side of that line.

My LinkedIn post: build on primitives, not on the convenience layers

Which makes this post a plot twist. Cluster Mode is the first AWS abstraction I would build on. It hands you an EKS cluster that Beanstalk maintains, an observability stack that is already wired up, and a container image built from your source with no Dockerfile in sight. The caveats are real, but the abstraction earns its place.

I built a small Node.js app, deployed it both ways, and wrote down everything that broke.

What Cluster Mode is

How Cluster Mode builds and runs an application: source code to CodeBuild, image to ECR, pod on EKS behind an ALB, metrics to CloudWatch

Elastic Beanstalk now has two ways to run the same application:

  1. Standard Mode gives every environment its own EC2 instances. Twenty small services means twenty environments to patch and pay for.
  2. Cluster Mode creates an EKS cluster with Auto Mode enabled and runs your application as a workload on it. One cluster carries many applications.

You hand it source code, a Dockerfile, or a prebuilt container image, and all three end up in the same place:

Three ways to feed Cluster Mode an application: source code, a Dockerfile, or a container image, all built by CodeBuild buildpacks into a running pod

Hand over source and Cloud Native Buildpacks containerize it in CodeBuild, push the image to ECR, and the cluster pulls it. No Dockerfile required.

Every environment gets an ALB with an ACM certificate, pod identity for AWS access, and horizontal autoscaling. Both modes coexist inside one application, so you can migrate environment by environment.

Standard ModeCluster Mode
Computeone EC2 environment per apppods on a shared EKS cluster
Source inputplatform bundles per runtimesource, Dockerfile, or image
HTTPSyou set it upALB and ACM by default
Spotsupportednot exposed
Deploysall-at-once to traffic-splittingrolling update, auto-rollback
Observabilityyou wire it upOTel and a dashboard, built in
Baseline costnoneEKS control plane, ~$0.10/hr
AWS Lambda Infographic

AWS Lambda on One Page (No Fluff)

Skip the 300-page docs. Our Lambda cheat sheet covers everything from cold starts to concurrency limits - the stuff we actually use daily.

HD quality, print-friendly. Stick it next to your desk.

Privacy Policy
Twice-a-month AWS newsletter, occasional product notes. No spam, no data selling.

What I deployed

Two environments, same app, both created through CloudFormation (the only IaC that accepted the new tier on day one):

app/         minimal Node.js HTTP server, returns JSON on / and /health
cluster/     Cluster Mode environment (tier Name=Cluster, Type=EKS)
standard/    Standard Mode environment, single instance, 100% spot

One apply created the Cluster Mode environment, the cluster, the node pool and the add-ons, built the image in CodeBuild, and put a pod behind an ALB.

The Cluster Mode environment in the Elastic Beanstalk console

curl https://eb-cluster-demo.eba-wepcihp8.eu-central-1.elasticbeanstalk.com/
{
    "message": "hello from elastic beanstalk",
    "mode": "cluster",
    "hostname": "deployment-eb-cluster-demo-654899f6bb-wrp5g"
}

Standard Mode was the control group: a t4g.nano on spot, one instance, no load balancer, roughly two dollars a month. It stayed boring, which is a compliment.

The Standard Mode environment in the Elastic Beanstalk console

The good parts

  • One cluster for many apps. No idle capacity per application. Elastic Beanstalk creates the cluster, node pools and add-ons, and keeps the add-on versions current.
  • Buildpacks instead of Dockerfiles. Node.js was detected, the image built and pushed to ECR. The build is a normal CodeBuild project, so the logs are where you already look.
  • HTTPS out of the box. Certificate, 443 listener and target group are configured without you touching any of it.
  • Sizing is option settings, not YAML. CPU, memory, replicas, autoscaling bounds and probes are flat key-value pairs with sane defaults: 250m CPU, 512Mi memory, port 8080.
  • The first deploy is slow, later ones are not. Roughly ten minutes to create the cluster, even for a Node app with zero dependencies. Later environments reuse it.

EKS cluster created by Elastic Beanstalk in Cluster Mode

CodeBuild project and build history created by Elastic Beanstalk

Where it hurts

Undocumented option namespaces

Cluster environments reject every classic namespace, including aws:elasticbeanstalk:environment and aws:ec2:vpc. On day one, the only way to find the replacements was the validation error:

Invalid option settings: namespace=aws:elasticbeanstalk:environment, option name=ServiceRole:
Unknown namespace 'aws:elasticbeanstalk:environment'. Valid namespaces are:
  aws:elasticbeanstalk:eks
  aws:elasticbeanstalk:eks:alb
  aws:elasticbeanstalk:eks:environment
  aws:elasticbeanstalk:eks:environment:autoscaling
  aws:elasticbeanstalk:eks:environment:deployment
  aws:elasticbeanstalk:eks:environment:liveness-probe
  aws:elasticbeanstalk:eks:environment:readiness-probe
  aws:elasticbeanstalk:eks:environment:startup-probe
  aws:elasticbeanstalk:eks:observability

Three IAM roles, three trust policies

RoleTrusted byNeeds
cluster-roleeks.amazonaws.comAssumeRole and TagSession
node-roleec2.amazonaws.comAssumeRole
observability-rolepods.eks.amazonaws.comAssumeRole and TagSession

The observability role is the trap. Beanstalk never assumes it; an EKS Pod Identity association for the metrics and logging agents does. Give it an elasticbeanstalk.amazonaws.com trust policy, the obvious guess, and the build dies with Trust policy of the role provided is invalid.

Trust relationships of the observability role

No Spot

I dumped the option surface of a running cluster environment: 102 settings, none mentioning Spot or capacity type. Beanstalk's own node pool, elastic-beanstalk-nodepool, is hard-pinned to on-demand:

karpenter.sh/capacity-type                    In   ['on-demand']
eks.amazonaws.com/instance-category           In   ['c', 'd', 'gr', 'hpc', 'i', 'im', 'is', 'm', 'r', 't', 'x', 'z']

EKS compute page showing the Elastic Beanstalk node pool and its nodes

The docs back this up: node capacity is "service-managed" and comes from EKS Auto Mode. There is a node-pool option in aws:elasticbeanstalk:eks:environment, but it only gives an environment dedicated nodes for isolation, not a different capacity type. Adding your own Spot NodePool to the cluster is a change Beanstalk treats as drift, which stops it from maintaining the cluster. Treat Spot as unsupported.

More broadly, the cluster is a normal EKS cluster and kubectl works, but the knobs stop at what Beanstalk exposes. No add-on selection, no node pool changes, and instance selection is a single instance-category letter. That is the trade for not running the cluster yourself.

Deploys and rollbacks

Cluster Mode drops the classic deployment policies. Deploys are Kubernetes rolling updates, by default with a surge of one and zero unavailability. The only alternative is Recreate, which is all at once. No immutable deployments, no traffic-splitting canary, no bake time.

I ran the same cycle on both modes: a good version, then a broken one that listens on the wrong port.

aws elasticbeanstalk update-environment \
  --environment-name eb-cluster-demo \
  --version-label v3-broken

On Cluster Mode, the broken pod crashed on startup, the rollout stalled, and the old version kept serving. Every curl through the whole window returned 200. Then Beanstalk rolled back on its own:

INFO  Cleaning up failed deployment before rolling back
INFO  Rolling back with applicationName='eb-cluster-demo' applicationVersion='v4-good'
INFO  Rollback completed successfully
ERROR Failed to update environment. Rollback completed to previous successful deployment.

Standard Mode did the opposite. Beanstalk reported Environment update completed successfully, health stayed Green, and the endpoint answered:

$ curl -i http://eb-standard-demo-env.eba-bsx5ybfa.eu-central-1.elasticbeanstalk.com/
HTTP/1.1 502 Bad Gateway

A single-instance environment has no second copy to fall back on. "Completed successfully" described the deployment, not the application. Health only went Yellow later. Cluster Mode behaved like a modern rollout here, and I did not expect that going in.

Observability, wired up for you

This is the part I would miss most going back to Standard Mode.

Beanstalk installs metrics-server, kube-state-metrics, fluent-bit, cert-manager and the EKS Pod Identity agent. Metrics go to CloudWatch through OpenTelemetry, and Beanstalk creates a dashboard alongside them. Anyone who has wired OpenTelemetry into ECS by hand knows that normally means a collector, its config, the IAM around it, and a week of figuring out which metrics arrive. Here it is one role ARN.

EKS add-ons installed by Elastic Beanstalk, all active

The catch: the dashboard reads from an ElasticBeanstalk/Application namespace, and in my environment that namespace stayed empty while the app served traffic:

$ aws cloudwatch list-metrics --namespace ElasticBeanstalk/Application
"Metrics": []

The panels sat at No data available. Whether that is timing on a young environment or a setup gap, I could not tell after a few hours. Verify it on your own cluster before relying on it.

Auto-created Elastic Beanstalk observability dashboard in CloudWatch

You can route each signal separately in aws:elasticbeanstalk:eks:observability. Metrics go to CloudWatch or Amazon Managed Prometheus, logs to CloudWatch or S3, traces to X-Ray, and custom takes your own OpenTelemetry collector pipeline for a third-party backend.

What it costs

Standard Mode, single instanceCluster Mode
Baseline$0EKS control plane, ~$0.10/hr, ~$73/mo
Computet4g.nano on spot, ~$0.003/hr, ~$2/moEKS Auto Mode, on-demand only
Load balancernoneALB
Break-even—roughly 20+ small apps per cluster

The control plane bills whether anything runs on it or not, about $2.40 a day for an idle environment. For a single small app, Standard Mode on spot came out roughly 35 times cheaper. The crossover depends on how many applications share the cluster, not on containers.

Terraform support on day one

hashicorp/aws cannot create a cluster environment, because tier is enum-locked:

Error: expected tier to be one of ["WebServer" "Worker"], got Cluster

hashicorp/awscc, the Cloud Control provider generated from the CloudFormation schemas, can:

resource "awscc_elasticbeanstalk_environment" "cluster" {
  application_name = "eb-cluster-demo"
  environment_name = "eb-cluster-demo-env"
  version_label    = "v1-697da24b"

  tier = {
    name = "Cluster"
    type = "EKS"
  }

  option_settings = [
    # cluster-role, node-role, observability-role, instance-category
  ]
}

The application version is the gap. Cluster environments reject the classic S3 source bundle and need an ImageConfiguration, which neither provider exposes. So the version comes from one CLI call, driven by a terraform_data resource:

aws elasticbeanstalk create-application-version \
  --application-name eb-cluster-demo \
  --version-label v1-697da24b \
  --source-bundle S3Bucket=eb-cluster-mode-demo-418272787065-eu-central-1,S3Key=app-697da24b.zip \
  --image-configuration '{"Build":{"Type":"buildpack",
      "Buildpack":"paketobuildpacks/builder-jammy-base",
      "CodeBuildServiceRole":"arn:aws:iam::418272787065:role/eb-cluster-demo-codebuild-role"}}'

Also worth knowing: Beanstalk creates its own CloudFormation stacks for the environment, the EKS cluster and the dashboard. They are not in your Terraform state and they stay behind when the environment goes away.

AWS noticed the failure before I did

Hours after a failed run, an email arrived: Proactive Reach Out regarding your Beanstalk Cluster environment. I had not opened a case. AWS opened it for me.

AWS Support case correspondence: a proactive reach-out from the Elastic Beanstalk Support team

The diagnosis was spot on: the observability role had no trust policy for pods.eks.amazonaws.com, which rolled back the EKS stack. That is the exact trap from the IAM table above, found by a human reading a rolled-back stack in a sandbox account on Basic Support.

I read that as a signal about the launch, not a support policy. The service team is watching rollbacks on new cluster environments. This is day-one software with people still standing behind it.

So, should you use it?

If you run a fleet of small services and are tired of paying for an environment each, a shared EKS cluster maintained by Beanstalk is a reasonable trade. The observability setup beats what I would wire up myself, and buildpacks lower the migration cost.

Skip it if you have one or two apps, need Spot, or depend on the deployment strategies Cluster Mode dropped. Either way, budget a debugging session for your first environment.

Fifteen years in, this is the most interesting thing Elastic Beanstalk has shipped in a long time. The rule still holds for the ECS-era wrappers. Cluster Mode is the exception I did not expect to find.