hard Subnetting & CIDR: usable addresses and the overlap trap
The mechanism: a CIDR prefix trades network bits for host bits
A CIDR block /n fixes the first n bits of a 32-bit IPv4 address as the
network prefix; the remaining 32−n bits are free to vary across
hosts. That directly gives the block size: 2(32−n) total addresses.
But "total addresses" and "usable host addresses" are not the same number — a slice
of every block is reserved and cannot be assigned to a host. Get this wrong and you either
under-provision a subnet or waste an entire migration renumbering it later.
Gotcha #1: usable is smaller than total — and cloud reserves more than classic IP
Classic IPv4 reserves exactly two addresses per block: the lowest address
(the network address, identifies the block itself, e.g. 10.0.1.0) and the
highest address (the broadcast address, e.g. 10.0.1.255, sends to every host
on the segment). So usable = 2(32−n) − 2.
Cloud VPC subnets reserve more. AWS reserves 5 addresses in every
subnet, not 2: the network address, a router address, one address reserved for DNS, one held for
future use, and the broadcast address. So usable(AWS) = 2(32−n) − 5.
Azure and GCP follow the same shape (a handful of reserved addresses per subnet) — always check
the provider's exact count before sizing, but budget for "several more than 2."
Traced arithmetic: three block sizes, worked exactly
| CIDR | Host bits | Total = 2(32−n) | Usable (classic, −2) | Usable (AWS, −5) |
|---|---|---|---|---|
/28 | 4 | 24 = 16 | 16 − 2 = 14 | 16 − 5 = 11 |
/24 | 8 | 28 = 256 | 256 − 2 = 254 | 256 − 5 = 251 |
/23 | 9 | 29 = 512 | 512 − 2 = 510 | 512 − 5 = 507 |
Traced sizing: "I need 500 hosts"
Walk the decision the way an engineer actually makes it:
- Try
/24first (it's the reflex size). Total = 28 = 256. That's already below 500 — a/24cannot fit 500 hosts under any accounting, classic or AWS. Reject it before even subtracting reservations. - Go up one bit to
/23(one fewer network bit = double the block). Total = 29 = 512. - Subtract reservations. Classic usable = 512 − 2 = 510 ≥ 500 ✓. On AWS, usable = 512 − 5 = 507 ≥ 500 ✓ — still enough, but only by 7 addresses of headroom.
Conclusion: /23, not /24 — and note the margin. 507 usable against a 500-host requirement leaves almost no room to add a node before you're forced to re-size again. That thin margin is exactly the seed of Pitfall #3 below.
Gotcha #2: the overlap trap — two networks with the same range cannot be connected
This is the pitfall that actually bites in production more than sizing does. VPC peering, a
site-to-site VPN, and Transit Gateway attachments all work by adding routes: "traffic to CIDR X goes
out this connection." If two networks you want to connect have overlapping CIDR ranges,
the router cannot build that route table — a packet addressed to 10.0.0.5 could
belong to either side, and there is no bit of information in the packet that says which. The
connection request is rejected outright; it is not a "slow" or "degraded" link, it simply cannot be
established.
Traced example
| Step | State |
|---|---|
| 1 | VPC-A is allocated 10.0.0.0/16 (default choice when the console/CLI is
used without a plan). |
| 2 | VPC-B, built independently by another team, is also allocated
10.0.0.0/16 — the same default. |
| 3 | A peering connection (or VPN, or Transit Gateway attachment) between A and B is requested. |
| 4 | Rejected. The provider refuses: the two CIDR blocks overlap, so a
route to 10.0.0.0/16 is ambiguous — it cannot tell whether a given address like
10.0.0.5 lives in A or in B. |
| 5 | Fix: re-allocate VPC-B to a disjoint range, e.g.
10.1.0.0/16. Now the route table is unambiguous: 10.0.0.0/16 → local
in A, 10.1.0.0/16 → peering connection to B. Peering succeeds immediately with no
other change. |
The only real difference between "works" and "rejected" here is which numbers were picked before either network existed — which is exactly why this has to be planned, not discovered.
Pitfalls a working engineer hits
- Sizing to total addresses, not usable ones. "A /24 has 256 addresses and we have 230 employees" sounds fine until AWS reservations take 5, not 2, and DHCP/monitoring/service accounts eat into the same pool — 251 usable is a much tighter fit than 256 looked like. Always subtract the provider's actual reservation count before comparing to a host estimate.
- The overlap trap. Two networks (VPCs, on-prem ranges, acquired-company networks)
that were each allocated
10.0.0.0/16,192.168.0.0/16, or any other "obvious default" independently cannot be peered, VPN'd, or put behind a Transit Gateway without renumbering one side or NAT-ing between them. This is discovered at connection time, often mid-project, and it is the single most common real-world subnetting failure — not miscounting bits. - Sizing too tight, forcing a renumber later. A subnet sized to exactly today's headcount (like the 507-of-500 example above) leaves no slack. The next hire, the next autoscaling burst, or the next service that needs its own IP forces a resize — and resizing a live subnet usually means allocating a new one and migrating everything across it, not simply growing the old one in place.
Selection & trade-offs: how much headroom, and who owns allocation
Size for growth + reservations vs. tight packing. A generously oversized block
(e.g. handing every team a /16 when they need a /22) wastes address space you
may need for other teams, but it means nobody ever has to renumber. A tightly packed allocation
(size exactly to the current headcount plus reservations) conserves address space and lets you carve
more subnets out of a limited private range, but any growth beyond the margin forces a disruptive
resize. Decide by cost of renumbering: if the network is small, early-stage, or easy to
touch, pack tight and resize later; if it's a production VPC with hundreds of attached resources,
route tables, and security groups, oversize up front — the cost of one extra unused
/24 is negligible next to a live migration.
Central IPAM vs. ad-hoc allocation. The alternative to "whoever spins up a VPC picks
whatever CIDR the console defaults to" is a central IP Address Management (IPAM) tool
(AWS VPC IPAM, or even a shared spreadsheet/wiki page treated as a source of truth) that hands out
non-overlapping ranges from a pre-planned supernet before any VPC exists. Ad-hoc allocation is faster
to start with zero process overhead, but it is exactly how two teams both end up on
10.0.0.0/16. IPAM costs a small amount of process discipline up front (someone must request
a range before creating a VPC) in exchange for guaranteeing every future peering/VPN/Transit Gateway
connection just works. Rule of thumb: a single-VPC prototype can skip IPAM; the moment
a second network might ever need to talk to the first (multi-account, multi-region, an eventual
acquisition), allocate from a plan, not from memory.
Takeaways
- Usable ≤ total. Total = 2(32−n); classic usable subtracts 2 (network + broadcast); cloud (AWS) subtracts 5. A /24 is 256 total but only 251 usable on AWS — size against the smaller number.
- 500 hosts needs a /23 (512 total, 507 usable on AWS), not a /24 (256 total — already short before any reservation math).
- Overlapping CIDR ranges cannot be peered, VPN'd, or transit-connected — routing becomes ambiguous. This bites more often than any sizing mistake; the fix is a renumber or a NAT bridge, both painful after the fact.
- Plan allocation before creation. A central IPAM (or even a disciplined shared sheet) that hands out non-overlapping ranges up front is cheaper than the alternative: discovering the collision the day two networks need to connect.
Synthesized from the AWS VPC documentation (subnet sizing & the 5 reserved addresses per subnet), RFC 950 (network and broadcast address reservation) and RFC 4632 (CIDR), and the AWS VPC peering documentation (overlapping CIDR blocks cannot be peered). Diagram hand-authored as SVG. Re-authored/Deepened for this guide.
🤖 Don't fully get this? Learn it with Claude
Stuck on Subnetting & CIDR: usable addresses and the overlap trap? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Build the mental picture, not memorization.
I just read a lesson on **Subnetting & CIDR: usable addresses and the overlap trap** (System Design) and want to truly understand it. Explain Subnetting & CIDR: usable addresses and the overlap trap from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Socratic — adapts to where you're stuck.
Teach me **Subnetting & CIDR: usable addresses and the overlap trap** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Active recall exposes what you missed.
Quiz me on **Subnetting & CIDR: usable addresses and the overlap trap** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Intuition + hook + flashcards for long-term memory.
Help me remember **Subnetting & CIDR: usable addresses and the overlap trap** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.