The single most expensive networking mistake organizations make in the cloud is using overlapping CIDR blocks. Two VPCs that both default to 10.0.0.0/16 cannot peer with each other. When the business decides to connect those VPCs — because of an acquisition, a multi-region rollout, or just an unrelated team needing to talk to your service — you have a re-IPing project on your hands. That is typically multiple weeks of work and a maintenance window.
This article walks through a tested CIDR planning pattern that prevents this problem from ever happening. It works for organizations going greenfield in the cloud and for ones that need to retrofit a coherent allocation onto an existing mess.
Why CIDRs must not overlap when peering
VPC peering, Transit Gateway, Virtual WAN, and every other cloud routing primitive uses the destination IP to decide where a packet goes. If two VPCs both contain 10.0.5.42, the router cannot decide which one to send a packet to. The cloud platforms know this and refuse to allow the peering at all.
The error message you get when you try is usually some variant of:
InvalidVpcPeeringConnectionId.NotFound: The VPC CIDR ranges overlap.
The fix at that point requires moving one VPC's workloads to a different CIDR, which means recreating subnets, ENIs, load balancers, and potentially every instance. It is the multi-day kind of fix.
The org-wide allocation chart
The right time to design CIDR allocation is before the first VPC is created. The wrong time is after you have 40 VPCs and someone needs them to talk to each other.
A standard pattern for organizations using all three major clouds:
10.0.0.0/8 Organization total (16,777,216 IPs) +-- 10.0.0.0/12 AWS (1,048,576 IPs) | +-- 10.0.0.0/16 aws-prod-us-east-1 | +-- 10.1.0.0/16 aws-prod-us-west-2 | +-- 10.2.0.0/16 aws-prod-eu-west-1 | +-- 10.3.0.0/16 aws-staging-us-east-1 | +-- 10.4.0.0/16 aws-staging-us-west-2 | +-- 10.5.0.0/16 aws-dev | +-- 10.6.0.0/16 aws-sandbox | +-- (10.7-10.15) reserved for future AWS VPCs +-- 10.16.0.0/12 Azure (1,048,576 IPs) | +-- 10.16.0.0/16 azure-prod-eastus | +-- 10.17.0.0/16 azure-prod-westus2 | +-- (10.18-10.31) reserved +-- 10.32.0.0/12 GCP (1,048,576 IPs) | +-- 10.32.0.0/16 gcp-prod-us-central1 | +-- (10.33-10.47) reserved +-- 10.48.0.0/12 On-premises (1,048,576 IPs) | +-- 10.48.0.0/16 datacenter-primary | +-- 10.49.0.0/16 datacenter-secondary | +-- (10.50-10.63) reserved for branches +-- 10.64.0.0/12 Acquisitions (1,048,576 IPs) | +-- reserved for newly-acquired company networks +-- 10.128.0.0/9 Future / DR (8,388,608 IPs)
Each cloud provider gets a /12 (1M addresses, 16 /16 VPCs). On-premises gets its own /12. Acquisitions get a separate block so you can integrate company networks without rushing a re-IP. The top half of 10/8 is reserved for the future — for new clouds, new regions, or anything else.
Within a VPC: per-region patterns
Inside each VPC, allocate subnets predictably so that subnets in different VPCs can be identified by their address. A standard three-tier, three-AZ pattern at /16 uses /20 subnets:
aws-prod-us-east-1 (10.0.0.0/16) +-- web-az-a (10.0.0.0/20) +-- web-az-b (10.0.16.0/20) +-- web-az-c (10.0.32.0/20) +-- app-az-a (10.0.48.0/20) +-- app-az-b (10.0.64.0/20) +-- app-az-c (10.0.80.0/20) +-- db-az-a (10.0.96.0/24) +-- db-az-b (10.0.97.0/24) +-- db-az-c (10.0.98.0/24) +-- tgw-attach (10.0.99.0/28 - 10.0.99.48/28) +-- (10.0.100.0/22 onward reserved for growth)
This carves the VPC into 16 /20 subnets max. Three tiers times three AZs is 9 subnets used, leaving 7 reserved for growth. Database subnets are smaller (/24) because RDS uses far fewer IPs than EKS or EC2 fleets.
You can design this layout interactively with our VLSM Designer in cloud mode, which applies AWS's 5-IP reservation rules automatically.
The CGNAT escape valve
For organizations that are running out of RFC 1918 space, or that need to integrate with networks that already use 10.0.0.0/8 heavily, RFC 6598 CGNAT space (100.64.0.0/10) is a 4-million-address third option. Cloud providers support it as a secondary CIDR.
AWS in particular benefits because Kubernetes (EKS) pods can consume thousands of VPC addresses per cluster. Putting pod IPs in CGNAT keeps your RFC 1918 space free for VMs, RDS, ELBs, and the things you actually peer with. See our article on Kubernetes pod CIDR sizing for the full pattern.
What to do when overlap is already present
If you are looking at this article because two VPCs you need to peer are already overlapping, the options are:
Option A: Re-IP one VPC
The painful but clean option. Pick the less-critical VPC and move its workloads to a non-overlapping CIDR. For AWS, this typically means:
- Add a new VPC with the correct CIDR.
- Recreate subnets, security groups, and route tables.
- Migrate workloads (instance by instance, using AMI snapshots).
- Update DNS, ELBs, and external service registrations.
- Decommission the old VPC.
Plan for 2-6 weeks depending on workload count and complexity.
Option B: Use private NAT
If re-IPing is genuinely impossible (regulated workload, frozen infrastructure), you can use private NAT to translate addresses at the peering boundary. AWS has a "private NAT gateway" feature for this. Azure supports it via private endpoints in some configurations. Operational complexity is high — you lose end-to-end address visibility, and troubleshooting becomes harder.
Option C: Transit Gateway with route segmentation
If only some subnets need to communicate, you can sometimes avoid the conflict by routing only the non-overlapping subnets through Transit Gateway. This works if your overlap is in a portion of the VPC that does not need cross-VPC connectivity. See our article on Transit Gateway vs VPC peering for the details.
Tooling to enforce the chart
Once you have a CIDR allocation chart, the chart itself becomes a critical document. Common practice:
- Store the chart in a shared location (Confluence, Notion, a Git repo).
- Require chart updates as part of the VPC provisioning workflow — no VPC gets created without an allocated CIDR from the chart.
- Use Terraform or similar to enforce this in code. Our IaC Export tool generates ready-to-use Terraform VPC modules from a designed allocation.
- Track active allocations in an IPAM tool. Our IPAM-Lite tracker uses your browser's localStorage; for team use you might want a server-backed tool.
Key takeaways
- Design CIDR allocation before the first VPC is created. Retrofitting is expensive.
- Use a top-down /12 per cloud pattern with room for future regions and acquisitions.
- Within a VPC, use /20 subnets for application tiers, /24 for databases, /28 for transit endpoints.
- Use CGNAT (100.64.0.0/10) as a secondary CIDR when RFC 1918 space is constrained — especially for EKS pod CIDRs.
- When CIDRs do overlap, re-IPing is usually the right fix. Private NAT is an emergency-only workaround.