VPC and subnets
After this you can answer: Why do the database and the cache sit in subnets the internet cannot reach?
Picture it
Section titled “Picture it”flowchart TB subgraph VPC["VPC 10.0.0.0/16"] P1["public-1<br/>10.0.0.0/24<br/>ALB, tasks"] P2["public-2<br/>10.0.1.0/24<br/>ALB, tasks"] R1["private-1<br/>10.0.10.0/24<br/>Postgres, Valkey"] R2["private-2<br/>10.0.11.0/24"] end I((Internet)) --> P1 I --> P2Each column is one availability zone. Only the public subnets touch the internet.
How it works
Section titled “How it works”- The VPC sets the address range. 10.0.0.0/16 gives about 65,000 private addresses. DNS support is on, so database endpoints resolve to private addresses.
- A subnet is a slice of that range in one availability zone. A
/24holds 256 addresses (AWS keeps 5 of them). - Public or private is decided by the route table, not by the subnet itself. A subnet whose route table sends 0.0.0.0/0 to the internet gateway is public. One without that route is private.
- Two of each, in two zones. An internet-facing ALB, an RDS subnet group and an ElastiCache subnet group all demand at least two availability zones.
In MiniTickets
Section titled “In MiniTickets”All four subnets are made in infra/src/network.ts → createNetwork:
minitickets-dev-public-1 and -public-2, minitickets-dev-private-1 and -private-2.
The private subnets have mapPublicIpOnLaunch false, so nothing there ever gets a public IP.
The api and web tasks run in the public subnets with a public IP. That is unusual, and it is on purpose: there is no NAT gateway, so a task needs a public IP to reach ECR, Secrets Manager and CloudWatch Logs. Their security groups still allow traffic only from the load balancer.
| From → to | What happens | What allows it |
|---|---|---|
| Private subnets → VPC | 10.0.10.0/24 and 10.0.11.0/24 are slices of 10.0.0.0/16 |
|
| Private subnets → Private route table | both private subnets use this route table: local route only |
|
| RDS Postgres → Private subnetsonly when dataEnabled = true | the database lives in the private subnets |
|
| ElastiCache Valkey → Private subnetsonly when dataEnabled = true | the cache lives in the private subnets |
|
See it in AWS
Section titled “See it in AWS”VPC → Subnets → filter minitickets-dev. Look at IPv4 CIDR, Availability Zone and the
Route table tab.
aws ec2 describe-subnets --filters Name=tag:Name,Values=minitickets-dev-private-*
Break it
Section titled “Break it”| Symptom | Cause | Where to look |
|---|---|---|
| New tasks stop: unable to pull secrets or registry auth | The task got no public IP, and there is no NAT | ECS → stopped task → Stopped reason |
| A review finds an internet route on a private subnet | It was associated with the public route table | VPC → Subnets → Route table tab |
| Creating the ALB fails | Only one public subnet was given | EC2 → Load Balancers → Network mapping |
Say it in an interview
Section titled “Say it in an interview”Follow-ups
Section titled “Follow-ups”Isn't a task with a public IP a security risk?
The public IP is a way out, not a way in: the web and api security groups allow inbound traffic only from the ALB’s security group. The risk is a wrong rule. A NAT gateway would add a second layer, at about 30+ USD a month.
Why two availability zones if we run one task?
The ALB, RDS and ElastiCache refuse to be created with fewer than two. It also means a second task could start in the other zone if one zone has trouble.
What happens if two subnet ranges overlap?
AWS refuses to create the second subnet: every address must belong to exactly one subnet.
pulumi preview shows the conflict before anything changes.
Advanced: Subnet values
The ranges come from publicCidrs and privateCidrs in infra/src/network.ts, placed in the
first two availability zones the region reports. RDS uses the DB subnet group
minitickets-dev-db-subnets; Valkey uses minitickets-dev-valkey-subnets. Both list only the
two private subnets.
Checkpoint
Section titled “Checkpoint”Answer these without scrolling up. If one feels hard, reread that section.
- What is the VPC’s address range?
- What makes a subnet public?
- Which pieces live in the private subnets?
- Why do the tasks have public IPs, and what stops the internet from calling them?
- Why two availability zones?
Redraw it from memory: the VPC with two public and two private subnets, their ranges, and what lives in each
Try this: on the map, select Private subnets and open the Connections tab: which pieces live there?
Read this book online: https://book.theversehub.in/