Scaling Spring Boot With an Auto Scaling Group (ASG) and Elastic Load Balancer (ELB)
Published · Updated
To scale Spring Boot horizontally on EC2, make every instance start the same version automatically, define that instance in a launch template, let an Auto Scaling Group maintain the fleet, and attach the ASG to an Application Load Balancer target group. Add load-balancer health checks and a measured scaling policy only after one instance can boot and become healthy without manual intervention.
This guide continues from deploying Spring Boot on EC2 behind an ALB. Read the ASG beginner guide first if minimum, desired, and maximum capacity are unfamiliar.
Target architecture
The request and management paths are different:
Client → ALB → target group → healthy Spring Boot instances
Launch template → ASG → launch/replace/terminate EC2 instances
The ASG registers new instances with the attached target group. The ALB routes requests based on target health. If Elastic Load Balancing health checks are enabled for the ASG, load-balancer health can also cause the group to replace an unhealthy instance.
AWS charges for the EC2 instances, load balancer, storage, data transfer, monitoring, logs, and other resources used by this lab. Set a conservative maximum capacity and complete the cleanup section.
1. Make the application safe to replicate
Before automating infrastructure, remove instance-specific assumptions:
- Do not store sessions or required files only on one instance.
- Make startup and database migrations safe when multiple instances boot together.
- Keep secrets out of the JAR, AMI, launch template, and user data.
- Use a read-only health endpoint that returns success only when the instance can receive requests.
- Shut down gracefully so in-flight requests have time to finish during scale-in.
Spring Boot Actuator exposes /actuator/health by default when Actuator is available. Secure any additional management endpoints because the Spring Boot documentation notes that they can expose sensitive information.
2. Choose a repeatable boot strategy
Every launched instance must obtain the same tested application version and start it without an engineer logging in. Two common lab strategies are:
- Immutable image: Install Java and the versioned JAR, configure systemd, verify the instance, and create an AMI. Publish a new AMI for each release.
- Minimal image plus bootstrap: Use a maintained base AMI and user data to fetch a versioned artifact from a controlled private location, verify it, install the service, and start it.
The first is easier to reason about during a beginner lab; the second avoids baking every application release into a full image but makes bootstrap reliability critical. Do not use unversioned “latest” artifacts. Do not place credentials in user data—use an instance profile with least-privilege access.
3. Create a versioned launch template
Create an EC2 launch template containing:
- the tested AMI or base image;
- an instance type with enough memory for the JVM;
- the application instance security group;
- an IAM instance profile rather than static AWS keys;
- storage settings; and
- user data only if the chosen boot strategy requires it.
The instance security group should accept the Spring Boot/health port only from the ALB security group. Public SSH is not required for application traffic; if administrative access is necessary, use a controlled route.
Launch templates support multiple versions. AWS’s launch-template guide explains how ASGs use the template’s instance configuration. Pin the ASG to the version you have tested rather than accidentally changing running behavior when a template default moves.
Before creating the ASG, launch one test instance from the exact template version. Confirm the service starts after reboot and the health endpoint responds locally.
4. Reuse or create the ALB target group
Use an Application Load Balancer target group with target type Instances, the application’s protocol and port (for example HTTP:8080), and a tested health path such as /actuator/health.
The ALB listener should forward to this target group. You attach the target group to an ASG for ALB, NLB, and GWLB integrations—not the load balancer object itself. AWS documents this distinction and the console flow in Attach a load balancer to your Auto Scaling group.
Review ELB fundamentals if listeners, rules, targets, and health checks are new.
5. Create the Auto Scaling Group
Create the ASG from the tested launch-template version. Select subnets in at least two Availability Zones that align with the ALB’s enabled zones. For a small availability lab, a starting shape might be:
- minimum capacity: 2;
- desired capacity: 2;
- maximum capacity: 4.
These are examples, not universal production values. Minimum 2 helps demonstrate redundancy, while maximum 4 limits accidental scale-out spend. Real bounds come from availability requirements, per-instance capacity tests, quotas, and cost controls.
Attach the existing target group during ASG creation. After the group launches instances, verify they appear in the target group and become healthy. AWS notes that instances launched by an attached ASG are registered automatically in its load balancing with Auto Scaling documentation.
6. Configure health replacement and startup timing
Turn on Elastic Load Balancing health checks for the ASG if application-level target health should participate in instance replacement. Set a health-check grace period long enough for Java, Spring, configuration retrieval, and application initialization.
Also set a realistic default instance warmup for scaling metrics. Grace period and warmup solve related but different timing problems:
- Health-check grace period prevents premature replacement while a new instance starts.
- Instance warmup controls when a new instance contributes to aggregated scaling metrics.
Measure cold-start behavior rather than guessing. A health endpoint that becomes successful before the application is truly ready can send traffic too early; one that depends on every external service can trigger fleet-wide unhealthy status during a shared outage.
7. Add a measured target-tracking policy
Target tracking adjusts desired capacity to keep a selected metric near a target. Useful predefined metrics include average ASG CPU utilization and ALB request count per target.
Request count per target is often easier to relate to an HTTP service when requests have reasonably consistent cost. CPU can work for CPU-bound services but misses exhaustion in memory, database pools, downstream quotas, or latency. Run a controlled load test in a non-production environment and find the per-instance throughput that still meets latency and error objectives.
Then configure:
- target tracking as the policy type;
- the metric that reflects actual load;
- a target value below the measured saturation point, leaving headroom; and
- the measured instance warmup.
AWS creates and manages the CloudWatch alarms for target tracking and generally prioritizes availability by scaling in more gradually. Do not edit those managed alarms manually; see AWS target tracking guidance.
8. Verify replacement and scale-out safely
First test self-healing without a traffic generator:
- Confirm both targets are healthy through the ALB.
- Record the current ASG instance IDs.
- Terminate one lab instance through EC2.
- Observe the ASG activity history, replacement launch, target registration, initial health, and eventual healthy state.
- Confirm requests continue through the ALB while at least one healthy target remains.
Then test scaling in a non-production account or isolated environment. Use a rate you control, respect the test tool’s safety limits, and watch application latency, error rate, ASG desired capacity, instance warmup, and target health. A short traffic burst may finish before a new JVM becomes useful, so autoscaling is not a substitute for baseline capacity.
Do not run an unbounded load test against a shared or production system. Do not assume a scale-out occurred merely because CPU briefly spiked; inspect ASG activity and CloudWatch metrics.
9. Plan deployments as well as scaling
An ASG does not automatically roll out a new application version safely. Create and test a new launch-template version, then use an appropriate controlled replacement mechanism such as an EC2 Auto Scaling instance refresh with health checks and rollback planning. Keep the old template/AMI available until the new fleet is verified.
Monitor at least ALB response codes and latency, healthy/unhealthy target counts, ASG capacity and activity failures, JVM/application metrics, and downstream saturation. Scaling the web tier can overload a database or external API faster, so protect shared dependencies.
10. Clean up
When finished, remove resources deliberately:
- Set the ASG capacity down and delete the ASG when no longer needed.
- Delete unused launch-template versions or the template.
- Delete the ALB and target group if they are not shared.
- Deregister and remove unused AMIs, and delete their backing snapshots where appropriate.
- Remove unused instances, volumes, security groups, logs, alarms, and public IP resources.
- Verify billing and resource inventories across Regions.
You now have the essential pattern: repeatable Spring Boot instances, automated fleet maintenance, health-aware routing, and evidence-based scaling. These are foundational concerns in the Cloud/AI Solutions Architect program.