Skip to content
AWS aws networking 5 min read

Internet Gateway

An internet gateway (IGW) is the door between your Virtual Private Cloud (VPC, your own private network inside AWS) and the public internet. Without it, resources in your VPC can talk to each other but have no way in or out of the wider internet. The IGW is what makes a subnet “public”: it lets instances with public IP addresses both reach the internet and be reached from it. It matters because almost every public-facing workload — a web server, an API, a load balancer — depends on an IGW being correctly wired up.

The three things that must align

A common surprise for beginners is that attaching an internet gateway by itself does nothing. Internet connectivity only works when three pieces line up at the same time:

  1. An IGW attached to the VPC. There is exactly one IGW per VPC. It is highly available and horizontally scaled by AWS — you do not manage its capacity.
  2. A route to it. A route table used by the subnet must have a route sending 0.0.0.0/0 (all IPv4 internet traffic) to the IGW. This is what turns a subnet into a public subnet.
  3. A public IP on the instance. The instance needs a public IPv4 address or an Elastic IP (a permanent, static public IP address you allocate to your account). A private-only instance cannot reach the internet through an IGW, no matter how the routes are set.

If any one of these is missing, traffic silently fails. There is no error — packets simply go nowhere.

Gotcha: A “public subnet” is not a setting on the subnet itself. A subnet is public purely because its route table has a 0.0.0.0/0 route pointing at an IGW. Move that route and the same subnet becomes private.

When to use an internet gateway (and when not)

Use an IGW when resources need two-way internet access using their own public IPs — for example, public web servers, NAT gateways, internet-facing load balancers, or bastion hosts.

Do not rely on an IGW for instances that must stay private but still need outbound access (to download patches, call external APIs, etc.). A private instance has no public IP, so an IGW can never route its traffic out. That exact gap is why NAT (Network Address Translation) exists: a NAT gateway lives in a public subnet, has its own public IP, and forwards outbound traffic on behalf of private instances — while still blocking unsolicited inbound connections.

ScenarioNeeds IGW?Needs NAT?
Public web server with a public IPYesNo
Private app server downloading updatesYes (for the NAT)Yes
Database with no internet accessNoNo
Internet-facing load balancerYesNo

Create and attach an internet gateway

Console steps

  1. Open the VPC console and choose Internet gateways in the left menu.
  2. Click Create internet gateway, give it a name like my-igw, and click Create internet gateway.
  3. On the new gateway, choose Actions → Attach to VPC.
  4. Select your VPC (for example vpc-0a1b2c3d) and click Attach internet gateway.
  5. Go to Route tables, open the route table associated with your public subnet, choose Edit routes, and add: Destination 0.0.0.0/0, Target the internet gateway (igw-0a1b2c3d). Save.

AWS CLI

# 1. Create the internet gateway
aws ec2 create-internet-gateway \
  --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=my-igw}]'

Output:

{
    "InternetGateway": {
        "InternetGatewayId": "igw-0a1b2c3d",
        "Attachments": [],
        "Tags": [{"Key": "Name", "Value": "my-igw"}]
    }
}
# 2. Attach it to your VPC
aws ec2 attach-internet-gateway \
  --internet-gateway-id igw-0a1b2c3d \
  --vpc-id vpc-0a1b2c3d

# 3. Add the default route to the public subnet's route table
aws ec2 create-route \
  --route-table-id rtb-0a1b2c3d \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id igw-0a1b2c3d

Output:

{
    "Return": true
}

A "Return": true confirms the route was added. Instances in subnets using rtb-0a1b2c3d can now reach the internet — provided they have a public IP.

Infrastructure as Code (Terraform)

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  tags   = { Name = "my-igw" }
}

resource "aws_route" "default_internet" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.main.id
}

Giving an instance a public IP

Even with the IGW and route in place, the instance still needs a public address. You have two options:

  • Auto-assign public IPv4 — enable it on the subnet, or pass it at launch. This IP is not permanent; it changes when the instance stops and starts.
  • Elastic IP (a permanent, static public IP address) — allocate one and associate it with the instance when you need a stable address.
# Enable auto-assign public IP on a subnet
aws ec2 modify-subnet-attribute \
  --subnet-id subnet-0a1b2c3d \
  --map-public-ip-on-launch

Cost note: The IGW itself is free, and there is no hourly charge for it. As of 2026, however, every public IPv4 address costs about $0.005 per hour (roughly $3.60/month each), whether it is auto-assigned or an idle Elastic IP. Release IPs you are not using.

Best practices

  • Treat an IGW as one of three required pieces — always verify the attachment, the 0.0.0.0/0 route, and the public IP together when debugging connectivity.
  • Keep only your truly public-facing subnets pointed at the IGW; route private subnets to a NAT gateway instead.
  • Use Elastic IPs only when you need a stable address (allow-listing, DNS); otherwise let AWS auto-assign to avoid idle-IP charges.
  • Restrict actual exposure with security groups and network ACLs — the IGW opens the path, but your firewall rules decide who gets through.
  • For IPv6, add a separate route for ::/0 to the IGW; IPv6 addresses are globally routable and need no NAT.
  • Audit unused Elastic IPs regularly to control IPv4 costs.
Last updated June 15, 2026
Was this helpful?