Courses Quizzes Articles Contact
Login
AWS VPC Step 2 of 14 · Easy · What a VPC is made of
TECH

CIDR blocks, subnets, and Availability Zones

Karen Created Oct 13, 2026 Updated Oct 13, 2026 4 min read

The VPC from the previous lesson is one range of addresses, 10.0.0.0/16. A subnet is a slice of that range placed in a single Availability Zone. This lesson splits the range, shows why one subnet cannot cover two zones, and why the numbers you pick now are hard to change after another network is connected.

Reading the CIDR

10.0.0.0/16 means “addresses that start with 10.0.” The /16 is how many leading bits are fixed. The remaining 16 bits can vary, so the range runs from 10.0.0.0 through 10.0.255.255: 65,536 addresses. A /24 fixes 24 bits, so 10.0.1.0/24 is only 10.0.1.0 through 10.0.1.255: 256 addresses.

A smaller prefix number is a larger network. /16 holds many /24s. The subnet’s CIDR has to sit entirely inside the VPC CIDR, and two subnets in the same VPC cannot overlap.

Five addresses you cannot use

AWS reserves the first four and the last address of every subnet. In 10.0.1.0/24 those are:

  • 10.0.1.0 — the network address
  • 10.0.1.1 — the VPC router
  • 10.0.1.2 — the DNS resolver
  • 10.0.1.3 — reserved for future use
  • 10.0.1.255 — the broadcast address, which AWS does not use, but still will not give you

A /24 therefore has 251 addresses you can assign. A /28 (16 addresses, 11 usable) is plenty for a load balancer and painful for a subnet you later want to fill with tasks. Carve smaller than the VPC, and leave room. Do not carve so small that the subnet is full the first time you add a zone.

One subnet, one zone

An Availability Zone is a separate data center (or group of them) inside the region. A subnet belongs to exactly one zone. There is no setting that stretches 10.0.1.0/24 across eu-west-2a and eu-west-2b.

To keep running when one zone fails, you create a second subnet from a different slice of the VPC, in the other zone. Instances in 10.0.1.0/24 and 10.0.2.0/24 still reach each other: both ranges are inside 10.0.0.0/16, and the VPC router delivers that traffic. The route that does it is the next lesson. The address plan has to allow it first.

Name CIDR Zone Role later in the course
public-a 10.0.1.0/24 eu-west-2a Load balancer and anything that must accept internet routes
public-b 10.0.2.0/24 eu-west-2b The same tier, in the other zone
private-a 10.0.11.0/24 eu-west-2a Databases and tasks with no inbound internet route
private-b 10.0.12.0/24 eu-west-2b The same tier, in the other zone

The names say “public” and “private” early so the later lessons have a stable layout. Nothing in this table makes a subnet public. A subnet becomes public when its route table sends internet traffic to an internet gateway and the instance has a public address. Both are still absent. The gap between 10.0.2.0/24 and 10.0.11.0/24 is spare space, not waste: you can add 10.0.3.0/24 in a third zone without renumbering.

Overlapping ranges come back later

Two networks can be connected only when their addresses do not overlap. If this VPC is 10.0.0.0/16 and the office, or a second VPC, is also 10.0.0.0/16, a packet for 10.0.1.20 has two homes. Routing cannot prefer one of them cleanly, and VPC peering will refuse the connection.

Pick the VPC CIDR before you launch anything you mean to keep. Changing it means creating a new VPC and moving the workloads. Adding a secondary CIDR later is possible and is how teams dig themselves out. It is not a plan.

Check three places before you lock the number: the default VPC in that account (172.31.0.0/16), any other VPC you already have, and the LAN range of any office you might connect with a VPN. 10.0.0.0/16 is fine in a lab. It is a frequent collision in companies that use 10.0.0.0/8 internally. A less common slice, such as 10.42.0.0/16, is the same kind of network with fewer surprises.

Subnets in Terraform

Each subnet names the VPC, the slice, and the zone. map_public_ip_on_launch stays off. A subnet you create does not assign public addresses unless you set this. The default VPC’s subnets are the ones that turn it on. Leaving it off here keeps that choice for a later lesson.

resource "aws_subnet" "app" {
  for_each = {
    a = { cidr = "10.0.1.0/24", az = "eu-west-2a" }
    b = { cidr = "10.0.2.0/24", az = "eu-west-2b" }
  }

  vpc_id                  = aws_vpc.main.id
  cidr_block              = each.value.cidr
  availability_zone       = each.value.az
  map_public_ip_on_launch = false

  tags = { Name = "app-${each.key}" }
}

When one subnet is the wrong default

  • The whole /16 is a single subnet in one zone. You cannot add a second zone without a new subnet, and you have no spare range left inside the VPC.
  • Both application tiers share a subnet. A database and a load balancer then have the same route table. You will want different routes for them, and a route table is attached per subnet, not per instance.
  • The CIDR matches a network you will connect. Peering and VPN fail, or traffic black-holes, months after the instances are running.

Leave the lesson with four /24s inside one /16, two zones, and no internet route. The next lesson is the table that decides where packets to those addresses actually go.

You're reading a free lesson from AWS VPC

The rest of the lessons are not for sale yet.