This was one of the most practical AWS labs I’ve done so far because it finally connected multiple cloud concepts into one working setup. Instead of thinking about one EC2 instance in isolation, this lesson focused on how real web traffic is usually handled in cloud environments: multiple backend servers, one frontend endpoint, health checks, and controlled routing.
The Problem with One Web Server
A single web server may be enough for a basic test, but it is not a strong production pattern. If traffic increases, performance can drop. If maintenance is needed, users may be affected. If the instance goes down, the whole site disappears.
The better pattern is to run multiple web servers and place a load balancer in front of them so users still see one entry point.
That is the core idea behind this lab. Two EC2 instances run the same web application, and the Application Load Balancer distributes traffic between them.
The Final Architecture
User
↓
Application Load Balancer
↓
Target Group
↓
web-01 web-02
The user never needs to know which backend server handled the request. They just access the load balancer DNS name, and the load balancer handles the rest.
Step 1: Launch Two EC2 Instances from a Launch Template
The lab starts from the launch template created earlier. That template already contains the AMI and the rest of the important configuration needed to create identical servers quickly.
From the launch template page, the next step is:
Actions → Launch instance from template
Two instances are launched at the same time. Initially they share the same name tag pattern, and then they are renamed clearly as:
- web-01
- web-02
This is important because both servers should behave the same way, but it is still useful to identify them separately during testing and troubleshooting.
Why the Launch Template Matters Here
If I had to configure everything manually each time, creating multiple backend servers would become repetitive and error-prone. Using the launch template means both instances are consistent. That consistency matters a lot when placing them behind a load balancer.
Step 2: Create the Target Group
After the two instances are running, the next step is to create a Target Group. A target group is basically a group of backend resources that the load balancer will send traffic to. In this case, those resources are EC2 instances.
The target group is created with:
- Target type: Instances
- Protocol: HTTP
- Port: 80
Since Apache is serving the website on port 80, the target group must match that.
Health Checks: The Most Important Part to Understand
One of the most useful parts of this lab was understanding health checks properly. The target group does not just blindly send traffic to any instance. It checks whether the instance is actually healthy enough to serve traffic.
In this lab, the health check configuration was based on:
- Protocol: HTTP
- Path: /
- Success code: 200
Since the site is being served from the default web root, using
/ is correct. If the application lived under a different
path, for example /app or /inner-peace, then
the health check path would also need to match that.
A lot of load balancer problems are not application problems at all. They are often health check configuration problems.
That was a very useful takeaway. If the service is actually running, but the health check is pointing to the wrong protocol, wrong port, or wrong path, the instance will still be marked unhealthy.
Health Threshold Changes
The instructor reduced the healthy threshold from the default value to 2. That means the instance only needed two successful health checks before being marked healthy. This makes the lab faster, while still keeping the logic realistic enough for learning.
Registering Targets
After the target group is created, both instances are selected and added into it. This step matters because simply having running instances is not enough. The load balancer can only route traffic to instances that are actually registered inside the target group.
Step 3: Create the Application Load Balancer
The next step is creating the actual Application Load Balancer (ALB). This is the public entry point users will access from the browser.
The important settings in this lab were:
- Name of the ALB
- Scheme: Internet-facing
- Multiple subnets selected
- HTTP listener on port 80
- Routing rule pointing to the target group
Internet-Facing vs Internal ALB
This part is important because AWS gives two choices: Internet-facing and Internal.
In this lab, the correct choice is Internet-facing because the site needs to be accessible from the browser over the internet.
Internet-facing ALB is public and meant for user traffic. Internal ALB is private and meant for service-to-service communication inside AWS.
An internet-facing ALB gets a public DNS name and is reachable from the internet. An internal ALB only uses private networking inside the VPC and is commonly used for backend services.
Internet-facing ALB → public websites and apps
Internal ALB → backend APIs and internal services
This distinction is very useful in real architectures. For example, a frontend app might sit behind an internet-facing ALB, while the backend API might sit behind an internal ALB.
Subnets and Availability
Multiple subnets were selected during the ALB setup. This is part of making the load balancer available across the region. Even if the backend instances are currently in one specific zone, the ALB itself can be prepared to span across multiple subnets and availability zones.
Step 4: Create a Separate Security Group for the Load Balancer
One subtle but very important detail in the lab is that the load balancer gets its own security group. This is not the same security group as the EC2 instances.
For the ALB security group, inbound rules allow:
- HTTP on port 80 from anywhere (IPv4 and optionally IPv6)
That makes sense because the ALB is the public entry point.
Step 5: Connect Listener to the Target Group
By default, the ALB listens on port 80. When a request arrives, the ALB needs to know where to send it. That routing is configured by pointing the listener to the target group created earlier.
HTTP : 80 → Forward to target group
At this point, the main setup is complete:
- Two EC2 instances are running
- Target group exists
- ALB exists
- Listener forwards traffic to the target group
It feels like everything should work immediately. But this is exactly where one of the most important debugging lessons happens.
The Real Problem: Instances Were Unhealthy
After the ALB became active, opening the ALB DNS name in the browser still did not work. The load balancer was up, but the target group showed both instances as unhealthy. That is a very common real-world situation.
The first instinct might be to blame Apache or the application. But in this lab, the web servers were actually working. They were reachable by public IP directly. So the real issue had to be somewhere between the load balancer and the instances.
The Security Group Mistake
The EC2 instance security group originally allowed HTTP only from my own IP. That was fine for direct browser testing, but it did not allow HTTP from the load balancer.
So from AWS’s perspective:
- I could access the web server directly
- The ALB could not access the web server
- The health checks failed
- The target group marked the instances unhealthy
This was the key lesson: the load balancer must be explicitly allowed in the instance security group.
The Fix
The solution was to update the EC2 security group:
- Remove HTTP access from my IP
- Add HTTP access where the source is the ALB security group
In simple words, the EC2 instances should trust the ALB, not the whole internet.
Allow HTTP : 80
Source = ALB Security Group
After saving this rule, the health checks started passing. Within a short time, the target group marked both instances as healthy.
Step 6: Final Test
Once the instances became healthy, the ALB DNS endpoint started working correctly. At that point, the browser could access the website through the load balancer instead of directly through the instance IP.
That was the real success of the lab. The important thing was not just “the site opens.” The important thing was that it opens through the proper architecture:
User → ALB DNS → Target Group → Healthy EC2 instances
Why This Lab Matters So Much
This lab felt important because it brought together several AWS ideas into one real flow:
- Launch multiple identical backend instances
- Group them into a target group
- Use health checks to decide who should receive traffic
- Create an ALB as the single public endpoint
- Secure the backend by allowing traffic only from the ALB
That is much closer to a real cloud deployment than simply launching one EC2 instance and opening it directly to the world.
What I Learned from the Security Side
One of the strongest lessons here was security group design. The backend instances should not simply accept public traffic if a load balancer is meant to sit in front of them. A better pattern is:
Internet → ALB
ALB → EC2 instances
Not:
Internet → EC2 directly
That small difference changes the architecture from a basic demo into a more production-like setup.
Cleanup and Resource Awareness
The lab also ends with an important cleanup reminder. After testing, the instances can be terminated, the load balancer deleted, and the target group cleaned up. AWS resources should not be left running without purpose.
One detail that remains is the AMI created earlier. That AMI still has a snapshot behind it, which is why the snapshot is not deleted immediately. It is tied to the image and can be used in later exercises.
Final Thoughts
This was one of the clearest examples of how AWS services work together. The Application Load Balancer was not difficult by itself, but the real learning came from understanding the full chain: instances, health checks, security groups, listeners, target groups, and DNS endpoint behavior.
The biggest takeaway for me was that real cloud architecture is not just about “making it work.” It is about making it work in the right flow, with clean routing and proper security boundaries.
After this lab, load balancers stopped feeling abstract. They started feeling like a practical and necessary part of building reliable web systems in AWS.
← Back to All Blogs