Load balancer and target groups
After this you can answer: How does the load balancer pick a task, and what makes a target unhealthy?
Picture it
Section titled “Picture it”flowchart TB B[Browser] -->|"HTTPS 443"| L["listener :443<br/>ACM certificate"] L -->|"rule 100: /trpc/*"| ATG["api target group<br/>port 4000, GET /health"] L -->|"default"| WTG["web target group<br/>port 3000, GET /"] ATG --> A["api task"] WTG --> W["web task"]How it works
Section titled “How it works”- The listener ends TLS. On port 443 the ALB decrypts HTTPS with our certificate. Inside the VPC it talks plain HTTP to the tasks.
- Rules are checked in priority order. Rule 100 matches
/trpc/*; anything else falls to the default action, the web target group. - The target group lists targets by IP. Fargate tasks have their own IPs; the ECS service registers each new task and removes stopped ones.
- Health checks decide. Every 15 s the ALB calls each target. 2 passes make it healthy, 3 failures (or no answer within 5 s) make it unhealthy, and it gets no more requests.
In MiniTickets
Section titled “In MiniTickets”The ALB minitickets-dev is internet-facing, sits in both public subnets and uses alb-sg
(infra/src/entry/alb.ts → createAlb). Port 80 answers every request with
a 301 redirect to https://. The TLS policy allows only TLS 1.2 and 1.3.
The api health check calls /health, not /ready: /health only says the process is up, so a short
database hiccup does not take every api task out at once. A stopping task gets 30 s
(deregistrationDelay) to finish requests in flight
(infra/src/entry/target-groups.ts → createTargetGroups).
The ALB is billed every hour it exists, which is why it sits behind the entryEnabled switch.
| From → to | What happens | What allows it |
|---|---|---|
| Application Load Balancer → Public subnetsonly when entryEnabled = true | one ALB node in each public subnet |
|
| Browser → Application Load Balanceronly when cdnEnabled = false | HTTPS on port 443; plain HTTP on port 80 only gets a redirect |
|
| Application Load Balancer → HTTPS listeneronly when cdnEnabled = false | the ALB hands each request to the listener for its port |
|
| CloudFront distribution → Application Load Balanceronly when cdnEnabled = true | fetches from the origin over plain HTTP on port 80, adding the X-Origin-Verify header |
|
| Application Load Balancer → HTTP listener with the origin headeronly when cdnEnabled = true | the ALB hands each request to its :80 listener |
|
| Application Load Balancer → ALB security grouponly when entryEnabled = true | the ALB's network interfaces use the ALB security group |
|
| Application Load Balancer → CloudWatch alarmsonly when entryEnabled = true | target 5xx + ALB 5xx ≥ 5 in 5 minutes → alb-5xx |
|
See it in AWS
Section titled “See it in AWS”EC2 → Target groups → minitickets-dev-api-tg-… → Targets: Health status and Health status
details.
aws elbv2 describe-load-balancers --names minitickets-dev
Break it
Section titled “Break it”| Symptom | Cause | Where to look |
|---|---|---|
| Every request returns 503 | The target group has no healthy target | Target group → Targets |
| Targets unhealthy: Request timed out | api-sg does not allow 4000 from alb-sg | Health status details |
/trpc/* calls get the Next.js 404 page | Rule 100 is missing | Listener → Rules |
Say it in an interview
Section titled “Say it in an interview”Follow-ups
Section titled “Follow-ups”What is the difference between a 502 and a 503 from the ALB?
503: no healthy target to send to. 502: a target was picked but closed the connection or sent a broken answer, for example a task dying during a Spot interruption.
Why not check /ready, which also pings the database?
If Postgres had a short hiccup, every api task would fail the check at once and the ALB would have
nobody to send to. With /health, the tasks stay and answer what they can.
ALB or Network Load Balancer?
An ALB understands HTTP: paths, headers, redirects, TLS with ACM. A Network Load Balancer works on TCP and is faster for raw connections, but cannot route by path. We need path routing.
Advanced: Listener and target group details
TLS policy ELBSecurityPolicy-TLS13-1-2-2021-06. dropInvalidHeaderFields removes invalid HTTP
header-name fields before forwarding. Target groups have no fixed name (a random suffix), because a
change like a new port replaces the group and two groups cannot share a name. In CloudFront mode
the listener is different: see the CloudFront chapter.
Checkpoint
Section titled “Checkpoint”Answer these without scrolling up. If one feels hard, reread that section.
- Where does TLS end, and how do the ALB and the tasks talk after that?
- Which rule sends a request to the api, and what happens to every other path?
- Who puts task IPs into a target group?
- What makes a target unhealthy?
- Why does the api health check use
/healthinstead of/ready?
Redraw it from memory: browser → listener :443 → rule 100 to the api target group, default to the web target group → tasks
Try this: on the map, select the HTTPS listener and read its rule and default action in the Connections tab
Read this book online: https://book.theversehub.in/