Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

ClickOps & Cloud Setup

VPC and VNet Design: Public, Private and Database Subnets Done Properly

VPC and VNet design decides how your workloads are addressed, isolated and connected. We plan non-overlapping CIDR ranges, spread subnets across availability zones, keep databases in private tiers with no internet route, and choose NAT, endpoints and peering to fit your traffic and budget.

Key takeaways

  • IP ranges are the hardest thing to change later, so plan CIDR blocks across all accounts and regions before building anything.
  • Public subnets hold only load balancers and NAT; applications and databases sit in private tiers.
  • Spread every tier across at least two availability zones, three for larger production systems.
  • NAT gateways and data transfer are common hidden costs, and gateway endpoints for S3 and DynamoDB are free.
  • Network design is written as Terraform so every environment is built the same way.

Why the network is the first design decision you cannot undo

Almost everything in a cloud account can be changed later. IP address ranges are the exception. Once a VPC exists with workloads, databases and peering attached, changing its CIDR means rebuilding. Teams discover this when a VPC runs out of addresses because Kubernetes pods took thousands of them, or when two networks they need to connect both use the same default range.

Networking is a core part of our ClickOps and cloud setup service, designed together with the account structure. If you run Kubernetes, the sizing decisions here matter even more; see our notes on Amazon EKS.

What the default VPC gets wrong

Every AWS account arrives with a default VPC: public subnets in each zone, auto-assigned public IPs and a route to the internet. It is convenient for a tutorial and poor for production. Resources launched into it are internet-adjacent by default, and the ranges are identical in every account and region, which guarantees overlap. We usually remove default VPCs from all regions in every account as part of the baseline, and build a deliberate network instead.

What good looks like

  • One written IP plan covering every account, environment and region.
  • At least two availability zones per tier, with identical layout in each.
  • Only load balancers, NAT and bastion-style entry points in public subnets.
  • Application workloads in private subnets, databases in isolated subnets with no internet route.
  • Gateway endpoints for S3 and DynamoDB, and interface endpoints where traffic volume justifies them.
  • Flow logs on, shipped to the log archive.
  • The whole thing defined in code.

How it works in practice

Address planning

Pick a supernet for the company, say a /8 or /12 from the private ranges, and carve it up: a block per region, then a block per account, then a block per VPC. Keep spare blocks unassigned. Check for conflicts with office networks, VPNs and any partner who will connect. This takes an afternoon and saves months.

The tiers

A representative layout for one VPC across three zones:

TierPurposeInternet route
PublicLoad balancers, NAT gatewaysVia internet gateway
Private applicationContainers, EC2, Lambda in VPCOutbound via NAT only
DatabaseRDS, ElastiCache, internal data storesNone

Smaller subnets for public and database tiers, larger for application tiers, since containers and pods consume many addresses.

Terraform

The community VPC module is a sensible base, though thin internal modules are often better once you know your pattern. A trimmed example:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = "acme-prod"
  cidr = "10.20.0.0/16"

  azs              = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
  public_subnets   = ["10.20.0.0/24", "10.20.1.0/24", "10.20.2.0/24"]
  private_subnets  = ["10.20.16.0/20", "10.20.32.0/20", "10.20.48.0/20"]
  database_subnets = ["10.20.8.0/24", "10.20.9.0/24", "10.20.10.0/24"]

  enable_nat_gateway     = true
  one_nat_gateway_per_az = true
  enable_flow_log        = true
}

The values are illustrative; ranges come from your IP plan. Version constraints are pinned and reviewed on upgrades.

Egress, endpoints and cost

NAT gateways charge by the hour and by data processed. Heavy traffic to S3 through NAT is a classic surprise bill. A gateway endpoint for S3 and DynamoDB routes that traffic privately at no charge. Interface endpoints for services like ECR, STS and CloudWatch cost per hour per zone, so they pay off only above certain traffic levels. We model this with your real usage rather than guessing, and link the findings to cost budgets. Our EKS cost calculator can help if Kubernetes is the main consumer.

Connecting accounts and sites

Peering is simple for two or three VPCs but does not scale, as it is not transitive. Transit Gateway centralises routing for many VPCs and VPNs at the cost of an hourly attachment fee and more design work. For hybrid links we plan Site-to-Site VPN first and Direct Connect only when bandwidth or latency demand it.

Security layers

Security groups are the primary control, referencing other groups rather than IP ranges where possible. Network ACLs are stateless and easy to get wrong, so we use them sparingly, mainly as a coarse backstop. Flow logs give visibility for investigations, and DNS design affects security too, which we cover in DNS setup.

Azure equivalent

Azure VNets follow the same logic with different mechanics. Subnets span a region’s zones, network security groups attach to subnets or interfaces, and user-defined routes steer traffic through a firewall in a hub network. Private Endpoints replace the role AWS interface endpoints play for PaaS services. We apply the same single IP plan and tiering discipline.

Decisions and trade-offs

Big VPC or many small ones? One large VPC per environment is easy to reason about. Many small VPCs isolate better but need more connectivity. Match it to your account structure.

IPv6. Dual-stack avoids some NAT cost and address exhaustion, but adds complexity in firewalls and tooling. We consider it case by case rather than by default.

Centralised egress inspection. A shared firewall gives one place for outbound policy, at real cost and latency. Reasonable for regulated environments, excessive for many startups.

When not to over-design. A single product with one VPC per environment does not need Transit Gateway or a firewall appliance.

Common failure modes

  • Overlapping CIDRs discovered at the moment of connection.
  • Subnets too small for container networking.
  • One NAT for everything, then a zone outage takes down egress.
  • Databases in public subnets because it made a quick test easier.
  • Undocumented manual route changes that Terraform later wants to revert.

Delivery and handover

You receive the IP plan, a diagram, the Terraform module and a short note on how to add a VPC or subnet safely. We build and destroy it in a scratch account first, so the first production build is a repeat. If you have an existing console-built VPC, we review it and decide whether to import or replace it, using the approach in our IaC migration plan.

How to tell it is working

  • No security group or route exposes a database to the internet.
  • Adding a new environment uses the module and an unused CIDR block, with no overlap checks by hand.
  • NAT and data transfer charges are understood and not growing unexpectedly.
  • Flow logs answer the question “what talked to this?” in minutes.

To review your current network, book a consultation.

References

How we deliver it

  1. 01

    Gather requirements

    We capture workloads, expected growth, on-premises or partner connectivity, compliance needs and which regions you will use.

  2. 02

    Plan the address space

    A single IP plan covers all accounts, environments and regions, leaving room to grow and avoiding overlap with offices and partners.

  3. 03

    Define the tiers

    Public, private application and isolated database subnets are laid out per availability zone, with routing for each.

  4. 04

    Choose egress and connectivity

    NAT gateways, VPC endpoints, Transit Gateway or peering are selected against traffic patterns and cost.

  5. 05

    Add network security and flow logs

    Security groups, network ACLs where useful, and flow logs to the log archive give control and evidence.

  6. 06

    Codify and test

    The design is delivered as a reusable Terraform module and tested by building it in a scratch account.

Tools and technologies

Amazon VPCTerraformNAT GatewayVPC EndpointsTransit GatewayRoute 53 ResolverVPC Flow LogsAzure Virtual NetworkAWS Network Firewall

Frequently asked questions

What is the right VPC CIDR size?
For most production VPCs a /16 gives ample room, though smaller ranges like /20 suit simple workloads. The real rule is to allocate from one central plan so ranges never overlap across accounts, regions, offices or partners. Overlap blocks peering and VPN connections later, and it is painful to correct.
Why separate database subnets from private subnets?
Separate subnets let you apply different routing and network rules. Database subnets typically have no route to the internet at all and accept traffic only from the application tier. That limits what a compromised application server can reach, and some services such as RDS use subnet groups built from these.
Do we need a NAT gateway in every availability zone?
For production, one per zone avoids cross-zone data charges and a zone-wide single point of failure. For development environments, a single shared NAT is often acceptable to save cost. This is a conscious trade-off between resilience and spend, and we state it in the design.
How does Azure VNet design differ?
Azure uses virtual networks with subnets, network security groups and route tables, typically in a hub-and-spoke layout with a hub for shared services and firewall. Subnets span all zones in a region, unlike AWS where subnets are zonal. The planning discipline around address space is identical.
Should each account have its own VPC?
Usually yes, since accounts are your isolation boundary. Where many accounts need shared services or controlled egress, a Transit Gateway hub connects them. For a small estate, separate VPCs with minimal peering are simpler. We choose the lightest design that meets your isolation and routing needs.

Talk to an engineer about vpc subnet design

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-08.