Terraform cidrsubnet calculator

Compute Terraform cidrsubnet, cidrsubnets and cidrhost results in your browser. Split a VPC CIDR into equal subnets and copy ready-to-paste HCL.

Your VPC or VNet range, e.g. var.vpc_cidr
Result
—

All subnets at this size

How Terraform's cidrsubnet() works

An IPv4 CIDR like 10.0.0.0/16 fixes the first 16 bits of the address and leaves 16 bits free. cidrsubnet() borrows newbits of those free bits to number the subnets, and netnum picks which one you get. With 8 newbits you get 28 = 256 subnets of size /24, numbered 0 to 255.

cidrsubnet("10.0.0.0/16", 8, 0)   # 10.0.0.0/24
cidrsubnet("10.0.0.0/16", 8, 1)   # 10.0.1.0/24
cidrsubnet("10.0.0.0/16", 4, 2)   # 10.0.32.0/20

A netnum that does not fit is an error: 8 newbits allow netnums 0 to 255, so cidrsubnet("10.0.0.0/16", 8, 256) fails instead of wrapping around.

Mixed sizes with cidrsubnets()

When subnets need different sizes, cidrsubnets() takes one newbits value per subnet and packs them in order, aligning each block to its own size. This example from the Terraform docs asks for three /20 blocks and one /24 from a /16:

cidrsubnets("10.1.0.0/16", 4, 4, 8, 4)
# ["10.1.0.0/20", "10.1.16.0/20", "10.1.32.0/24", "10.1.48.0/20"]

The /24 takes 10.1.32.0, but the next /20 starts at 10.1.48.0, not 10.1.33.0, because a /20 must begin on a multiple of 16 in the third octet. The range 10.1.33.0 to 10.1.47.255 stays unused.

A common VPC layout

A typical AWS setup is one public and one private subnet per availability zone. Rather than hard-coding ranges, compute them from the VPC CIDR so the whole layout moves if the VPC range changes:

locals {
  azs             = ["eu-west-3a", "eu-west-3b", "eu-west-3c"]
  public_subnets  = [for i, az in local.azs : cidrsubnet(var.vpc_cidr, 8, i)]
  private_subnets = [for i, az in local.azs : cidrsubnet(var.vpc_cidr, 8, i + 10)]
}

Leaving a gap between the public and private ranges (indexes 0–2 and 10–12 above) gives you room to add zones later without renumbering anything. To lay out every tier and AZ at once, with spare AZ slots and ready-to-copy Terraform, use the AWS VPC subnet planner.

Pitfall: renumbering live subnets

Changing newbits, or inserting a value in the middle of a cidrsubnets() list, moves every subnet that comes after it. On AWS, cidr_block on aws_subnet cannot change in place, so Terraform plans to replace every subnet that moved, and whatever runs in those subnets goes with them. The Terraform docs warn not to change existing arguments once addresses are in use. Append new values to the end of the list instead, or give each subnet a fixed netnum as in the layout above.

FAQ

What does cidrsubnet() do in Terraform?

cidrsubnet(prefix, newbits, netnum) takes a parent CIDR block, makes the prefix longer by newbits, and returns the subnet with index netnum. For example cidrsubnet("10.0.0.0/16", 8, 2) adds 8 bits to /16 to get /24 subnets and returns the third one, 10.0.2.0/24.

How do I choose newbits?

newbits is the target prefix length minus the parent prefix length. To get /24 subnets from a /16 VPC, newbits is 8. To fit N equal subnets you need at least log2(N) newbits, rounded up: 3 subnets need 2 bits, 6 subnets need 3 bits.

What is the difference between cidrsubnet and cidrsubnets?

cidrsubnet returns one subnet by index. cidrsubnets(prefix, newbits...) returns a list of consecutive subnets of possibly different sizes, packed one after another and each aligned to its own size. It is handy when you want a few large subnets and a few small ones without computing indexes by hand.

Why does my result differ from the IP I typed?

If the parent CIDR has host bits set, such as 10.0.0.5/16, Terraform and this calculator use its network address (10.0.0.0/16). The calculator shows a notice when that happens.

How many usable IPs does an AWS or Azure subnet have?

Both AWS and Azure reserve 5 addresses in every subnet: the network address, the next three, and the last one. A /24 therefore has 251 usable addresses for resources instead of 254. GCP reserves 4.

Is my data sent anywhere?

No. The calculator runs entirely in your browser with JavaScript. Nothing you type leaves the page.

More tools