Back to VPC & Networking
Q1Question 1 of 8

VPC, Subnet, and What Makes a Subnet Public versus Private

Key Concepts
  • A VPC is a logically isolated virtual network in an AWS Region with its own IP address range (CIDR block), route tables, and gateways.
  • A VPC is private and isolated by default; nothing reaches the internet until you explicitly add gateways and routes.
  • A subnet is a sub-range of the VPC CIDR that lives in exactly one Availability Zone, grouping resources together.
  • A subnet is public when its route table has a 0.0.0.0/0 route to an Internet Gateway.
  • A subnet is private when its route table has no route to an Internet Gateway, regardless of other routes.
  • AWS reserves 5 IP addresses in every subnet, so a /24 gives 251 usable addresses, not 256.
  • The three-tier layout uses public subnets for the ALB and NAT, private subnets for application servers, and isolated subnets for databases.

Definition

A VPC is your private network in AWS, a subnet is a slice of it in one Availability Zone, and a subnet is public only if its route table has a route to an Internet Gateway.
  • VPC (Virtual Private Cloud) – A logically isolated virtual network you define inside an AWS Region, with its own CIDR block, route tables, and gateways.
  • Subnet – A sub-range of the VPC's CIDR that lives in exactly one Availability Zone, used to group resources and apply routing and firewall rules.
  • Public Subnet – A subnet whose route table has a route sending 0.0.0.0/0 to an Internet Gateway, allowing instances with a public IP to reach and be reached from the internet.
  • Private Subnet – A subnet whose route table has no route to an Internet Gateway, making its instances invisible to the public internet.
  • Internet Gateway (IGW) – A VPC component that provides two-way internet connectivity for public subnets.

A VPC is National Bank of India's own private office building, walled off from every other tenant, with its own internal address scheme. A subnet is one floor of that building, and each floor sits in exactly one wing (Availability Zone). A floor is public if there is a hallway connecting it to the street-facing main entrance (Internet Gateway) so visitors can come and go, and it is private if there is no such hallway at all.

Understanding the Concepts

What is a VPC?

A VPC (Virtual Private Cloud) is the foundation of networking in AWS. When you create it you choose a CIDR block, for example 10.0.0.0/16, which gives you 65,536 private IP addresses to carve up. Nothing inside the VPC can talk to the internet or to another VPC unless you explicitly add gateways and routes, so a VPC is private and isolated by default.

JAVA
import software.amazon.awssdk.services.ec2.Ec2Client;
import software.amazon.awssdk.services.ec2.model.CreateVpcRequest;

public class CreateBankVPC {
    public static void main(String[] args) {
        Ec2Client ec2 = Ec2Client.create();
        var vpc = ec2.createVpc(CreateVpcRequest.builder()
                .cidrBlock("10.0.0.0/16")  // 65,536 addresses
                .build());
        System.out.println("VPC ID: " + vpc.vpc().vpcId());
        // This VPC is completely isolated until you add gateways
    }
}

What is a subnet?

A subnet is a smaller CIDR carved out of the VPC range, such as 10.0.1.0/24 (256 addresses). A subnet lives in exactly one Availability Zone, so to be highly available you create matching subnets in several zones. AWS reserves five addresses in every subnet: the network address, the VPC router, the DNS server, a future-use address, and the broadcast address, so a /24 gives you 251 usable addresses.

BASH
# Create subnets in different AZs for high availability
aws ec2 create-subnet --vpc-id vpc-0abc --cidr-block 10.0.1.0/24 --availability-zone ap-south-1a
aws ec2 create-subnet --vpc-id vpc-0abc --cidr-block 10.0.2.0/24 --availability-zone ap-south-1b
aws ec2 create-subnet --vpc-id vpc-0abc --cidr-block 10.0.3.0/24 --availability-zone ap-south-1c

What makes a subnet public?

A subnet is public when its associated route table has a route for 0.0.0.0/0 pointing to an Internet Gateway. Resources in the subnet with a public IP can send and receive internet traffic. The route is the sole difference.

DIAGRAM
# Public subnet route table
10.0.0.0/16   → local          (internal VPC traffic)
0.0.0.0/0     → igw-0abc123     (internet, both directions) ← makes it PUBLIC

What makes a subnet private?

A subnet is private when its route table has no 0.0.0.0/0 route to an Internet Gateway. Resources there can reach the internet only indirectly through a NAT Gateway for outbound, or not at all. The absence of the IGW route is what makes it private.

DIAGRAM
# Private subnet route table (with NAT for outbound)
10.0.0.0/16   → local
0.0.0.0/0     → nat-0xyz789    (outbound only, no inbound) ← keeps it PRIVATE

# Fully isolated private subnet (no internet at all)
10.0.0.0/16   → local
# No default route → completely isolated from the internet

How do you design the three-tier banking VPC?

The typical banking layout uses three tiers of subnets across multiple Availability Zones:

  • Public subnets – For the Application Load Balancer and NAT Gateway only. These are the only subnets with an IGW route.
  • Private app subnets – For application servers (settlement service, transfer service). Outbound internet via NAT Gateway.
  • Private database subnets – For RDS instances. No internet route at all, fully isolated.
DIAGRAM
# Three-tier banking VPC layout
┌──────────── VPC 10.0.0.0/16 ──────────────┐
│                                             │
│  Public Subnets (IGW route):                │
│    10.0.1.0/24 (AZ-a)  ALB, NAT Gateway    │
│    10.0.2.0/24 (AZ-b)  ALB, NAT Gateway    │
│                                             │
│  Private App Subnets (NAT route):           │
│    10.0.11.0/24 (AZ-a)  Settlement service  │
│    10.0.12.0/24 (AZ-b)  Transfer service    │
│                                             │
│  Private DB Subnets (no internet):          │
│    10.0.21.0/24 (AZ-a)  RDS primary         │
│    10.0.22.0/24 (AZ-b)  RDS standby         │
└─────────────────────────────────────────────┘

How many addresses does a subnet actually have?

  • AWS reserves five addresses in every subnet:
  • First address (10.0.1.0): network address
  • Second address (10.0.1.1): VPC router
  • Third address (10.0.1.2): DNS server
  • Fourth address (10.0.1.3): reserved for future use
  • Last address (10.0.1.255): broadcast address

So a /24 subnet has 256 total addresses minus 5 reserved, giving 251 usable addresses.

JAVA
public class SubnetAddressCalculation {
    public static int usableAddresses(int prefixLength) {
        int total = (int) Math.pow(2, 32 - prefixLength);
        return total - 5; // AWS reserves 5 addresses
    }

    public static void main(String[] args) {
        System.out.println("/24 usable: " + usableAddresses(24)); // 251
        System.out.println("/20 usable: " + usableAddresses(20)); // 4091
        System.out.println("/28 usable: " + usableAddresses(28)); // 11 (minimum useful)
    }
}

What are common mistakes?

The first mistake is confusing public IP with public subnet. A subnet is public because of its route table, not because instances in it have public IPs. An instance in a public subnet without a public IP still cannot be reached from the internet.

The second mistake is putting database instances in a public subnet. Even with tight Security Groups, having a route to the Internet Gateway means the database is one misconfiguration away from exposure.

The third mistake is creating subnets that are too small. A /28 gives only 11 usable addresses, which fills up quickly with auto-scaling, and you cannot resize a subnet CIDR in place.

JAVA
public class SubnetMistakes {
    // WRONG: RDS in a public subnet
    // Even with Security Group, IGW route exists = exposure risk

    // CORRECT: RDS in a private subnet with no IGW route
    // No route to internet = no exposure, by construction

    // WRONG: /28 subnets for auto-scaling workloads
    // 11 usable IPs = runs out with 12 instances

    // CORRECT: /24 minimum for app subnets, /20 for EKS
}

What should a senior engineer know?

A senior engineer knows that giving a subnet a public route is necessary but not sufficient for an instance to be reachable. The instance also needs an actual public or Elastic IP, and the Security Group and NACL must allow the traffic. Public versus private is a property of the subnet's routing; whether a specific instance is reachable layers the IP and the firewalls on top.

They also know that VPC CIDR ranges cannot overlap with peered VPCs or Transit Gateway connections, and they plan the CIDR allocation centrally across the organization.

BASH
# Check if a subnet is public by examining its route table
aws ec2 describe-route-tables \
  --filters "Name=association.subnet-id,Values=subnet-0abc" \
  --query 'RouteTables[*].Routes[?DestinationCidrBlock==`0.0.0.0/0`].GatewayId'
# If output contains "igw-xxxx" → public subnet
# If output is empty or contains "nat-xxxx" → private subnet

Visual Overview

DIAGRAM
┌──────── VPC, Subnets, Public vs Private ────────┐
│                                                   │
│  VPC: 10.0.0.0/16 (isolated by default)           │
│                                                   │
│  ┌──── Public Subnet (10.0.1.0/24) ────┐         │
│  │ Route: 0.0.0.0/0 → igw-0abc (PUBLIC)│         │
│  │                                      │         │
│  │ ALB ←── internet traffic ──→ IGW     │         │
│  │ NAT GW                               │         │
│  └──────────────────────────────────────┘         │
│                  │                                 │
│                  ▼                                 │
│  ┌──── Private App Subnet (10.0.11.0/24) ──┐     │
│  │ Route: 0.0.0.0/0 → nat-0xyz (PRIVATE)   │     │
│  │                                          │     │
│  │ Settlement Service (no public IP)        │     │
│  │ Outbound only via NAT, no inbound        │     │
│  └──────────────────────────────────────────┘     │
│                  │                                 │
│                  ▼                                 │
│  ┌──── Private DB Subnet (10.0.21.0/24) ───┐     │
│  │ Route: local only (FULLY ISOLATED)       │     │
│  │                                          │     │
│  │ RDS PostgreSQL (no internet at all)      │     │
│  └──────────────────────────────────────────┘     │
│                                                   │
│  Key: IGW route = PUBLIC, no IGW route = PRIVATE  │
└───────────────────────────────────────────────────┘

Key Takeaway

A VPC is a logically isolated virtual network that I define inside an AWS Region, with its own IP address range as a CIDR block, its own route tables, and its own gateways. The important thing is that a VPC is private and isolated by default – nothing inside it can reach the internet or another VPC until I explicitly add a gateway and a route – which is exactly the safe starting point a bank wants. When I create one I pick a CIDR like 10.0.0.0/16, which gives me about sixty-five thousand private addresses to carve up.

A subnet is a smaller slice of that CIDR, such as 10.0.1.0/24, and it lives in exactly one Availability Zone, so for high availability I create matching subnets across several zones. AWS reserves five addresses in every subnet for the network, the router, DNS, a future-use slot, and broadcast, so a /24 actually gives me 251 usable addresses.

The heart of the question is what makes a subnet public versus private, and the answer is a single routing rule. Every subnet is associated with one route table. If that route table has a route for 0.0.0.0/0 pointing to an Internet Gateway, the subnet is public and resources there with a public IP can send and receive internet traffic. If there is no such route to an Internet Gateway, the subnet is private – resources there reach the internet only indirectly through a NAT Gateway for outbound, or not at all.

At National Bank of India I use the standard three-tier layout. The customer-facing load balancer and the NAT Gateway sit in public subnets with an Internet Gateway route, the application servers sit in private subnets whose default route goes to the NAT Gateway for outbound patches only, and the database sits in its own private subnets with no internet route at all. One senior point is that a public route is necessary but not sufficient for an instance to actually be reachable – the instance still needs a public IP and the Security Group and NACL must allow the traffic.

Remember one sentence: A subnet is public when its route table has a 0.0.0.0/0 route to an Internet Gateway, and private when it does not.

---

Share
Use ← → arrow keys to navigate