/20 subnet: 255.255.240.0, 4,096 addresses

4,096 addresses (4,094 usable hosts)

A /20 has the netmask 255.255.240.0 and holds 4,096 addresses, 4,094 of them usable hosts. It covers 16 consecutive values of the third octet: 172.31.0.0/20 runs from 172.31.0.0 to 172.31.15.255, the same span as 16 /24s side by side.

The numbers

Network        172.31.0.0/20
Broadcast      172.31.15.255
Netmask        255.255.240.0
Wildcard       0.0.15.255
First host     172.31.0.1
Last host      172.31.15.254

Only the first and last addresses are reserved, so 172.31.1.0, 172.31.1.255 and 172.31.15.0 are ordinary hosts here.

How it fits

A /16 holds 16 /20s and a /19 holds two. A /20 splits into 2 /21s, 4 /22s or 16 /24s; the tool below lists the /24s. The boundaries fall on multiples of 16 in the third octet: .0, .16, .32 … .240.

Where you’ll see it

  • AWS default subnets. Every region’s default VPC is 172.31.0.0/16, with one /20 default subnet per availability zone: 172.31.0.0/20, 172.31.16.0/20, 172.31.32.0/20 and so on. AWS reserves 5 addresses in each, leaving 4,091.
  • Your own VPC layouts. A /16 cut into /20s gives 16 subnets of about 4,000 hosts: enough for public, private and data tiers in three zones, with seven left for later.
  • Docker. Once Docker’s default pools have used 172.17.0.0/16 through 172.31.0.0/16, it hands out /20s from 192.168.0.0/16: 192.168.0.0/20, 192.168.16.0/20 and on. Those can land on top of a home or office LAN.

Gotchas

  • A /20 starts on a multiple of 16. 172.31.8.0/20 has host bits set: the tool reads it as 172.31.0.0/20, and stricter parsers, such as Python’s ipaddress, reject it. If you meant a block that starts at 172.31.8.0, the largest one that does is 172.31.8.0/21, which runs to 172.31.15.255.
  • Docker on a 192.168 LAN. If docker network inspect shows Compose networks in 192.168.x.0/20, set default-address-pools in /etc/docker/daemon.json to a range your LANs and VPNs don’t use, then recreate the networks.

In your stack

# Terraform: one /20 per availability zone
[for i in range(3) : cidrsubnet("172.31.0.0/16", 4, i)]
# ["172.31.0.0/20", "172.31.16.0/20", "172.31.32.0/20"]
cidrnetmask("172.31.0.0/20")           # "255.255.240.0"
import ipaddress
zone = ipaddress.ip_network("172.31.0.0/20")
len(list(zone.subnets(new_prefix=24)))      # 16
aws ec2 create-subnet --vpc-id vpc-0123456789abcdef0 --cidr-block 172.31.48.0/20 --availability-zone us-east-1d

Try it in the CIDR & Subnet Calculator

172.31.0.0/20 Private (RFC 1918)

Network172.31.0.0/20
Broadcast172.31.15.255
Netmask255.255.240.0
Wildcard0.0.15.255
Mask, binary11111111.11111111.11110000.00000000
First host172.31.0.1
Last host172.31.15.254
Addresses4096
Usable hosts4094
KindPrivate (RFC 1918)

16 subnets of /24.

SubnetFirstLast
172.31.0.0/24172.31.0.0172.31.0.255
172.31.1.0/24172.31.1.0172.31.1.255
172.31.2.0/24172.31.2.0172.31.2.255
172.31.3.0/24172.31.3.0172.31.3.255
172.31.4.0/24172.31.4.0172.31.4.255
172.31.5.0/24172.31.5.0172.31.5.255
172.31.6.0/24172.31.6.0172.31.6.255
172.31.7.0/24172.31.7.0172.31.7.255
172.31.8.0/24172.31.8.0172.31.8.255
172.31.9.0/24172.31.9.0172.31.9.255
172.31.10.0/24172.31.10.0172.31.10.255
172.31.11.0/24172.31.11.0172.31.11.255
172.31.12.0/24172.31.12.0172.31.12.255
172.31.13.0/24172.31.13.0172.31.13.255
172.31.14.0/24172.31.14.0172.31.14.255
172.31.15.0/24172.31.15.0172.31.15.255

Runs in your browser. Nothing you enter is sent anywhere.