All articles
61 articles · updated weekly See our Tools
All articles
Tutorials

IP Addresses: IPv4 vs IPv6, exhaustion, NAT, and why it still matters

IPv4 ran out in Latin America in 2020. A practical breakdown of notation, NAT's tradeoffs, IPv6 changes, and what it means for developers writing real systems.

COVER · Tutorials

In 2011, IANA distributed its last IPv4 address blocks to the regional registries. LACNIC, which manages Latin America, exhausted its pool in 2020. Today, when an ISP needs to add a new customer, the options are: pay a premium on the secondary market for IPv4 blocks, stack another NAT on top of existing NAT, or finally turn on IPv6. This is an addressing problem that most developers touch every day without realizing it — and it explains why 10.0.0.x shows up on your network interface instead of the IP the world actually sees.

If you want to understand what happens before an IP address is even used — how DNS resolves names, how TCP establishes connections — there's a companion post covering that: How the internet works: DNS, HTTP, and what happens before the first byte. This one focuses on the addressing layer itself.


What an IP address actually is

An IP address is a numeric identifier assigned to each network interface. Not each machine — each interface. A server with two NICs has two IPs. A Docker container has its own. A split-tunnel VPN creates a virtual interface with yet another.

The function is dual: it identifies the host and indicates its position in the network topology. Routers use the destination IP to decide where to forward each packet. Without that, there's no routing — just flooding.

There are two address spaces in active use: IPv4 and IPv6. These aren't just versions of the same protocol in a backward-compatible sense — they're distinct protocols that coexist in current infrastructure through dual-stack deployments.


IPv4: notation, limits, and the math of exhaustion

IPv4 uses 32-bit addresses, written as four decimal octets separated by dots:

192.168.1.100

Each octet ranges from 0 to 255. The total space is 2³² = 4,294,967,296 addresses — under 4.3 billion. That seemed like a lot in 1981. Today there are over 15 billion connected devices.

Part of that space was never available for public use. Several blocks are reserved:

Range Use
10.0.0.0/8 Private network (RFC 1918)
172.16.0.0/12 Private network (RFC 1918)
192.168.0.0/16 Private network (RFC 1918)
127.0.0.0/8 Loopback
169.254.0.0/16 Link-local (APIPA)
224.0.0.0/4 Multicast

The private ranges (RFC 1918) were the emergency solution for exhaustion: instead of giving each device a public IP, an entire network of devices shares a single public IP through NAT.

NAT: the workaround that became the standard

NAT (Network Address Translation) is the mechanism that lets your home router allow 20 devices to share one public IP. The router maintains a mapping table: when a packet goes out, it records the internal IP and port, replaces them with the public IP and a different port, then reverses the process when the response comes back.

Internal device: 192.168.1.50:45231
Router (public IP): 203.0.113.1:60001
Destination server sees: 203.0.113.1:60001

This works well for connections initiated outbound. For inbound connections — hosting a server, P2P, VoIP, online gaming — NAT breaks the end-to-end model of the internet and requires workarounds like port forwarding, STUN, TURN, or hole punching.

Carrier-Grade NAT (CGN or CGNAT) is the industrial version: the ISP applies NAT before traffic even reaches the customer's router. The result: multiple customers share the same public IP, the customer has no control over port mappings, and hosting anything from home becomes impossible without purchasing a static IP separately.


IPv6: notation, scale, and what changes in practice

IPv6 uses 128-bit addresses, written as eight groups of four hex digits separated by colons:

2001:0db8:85a3:0000:0000:8a2e:0370:7334

Leading zeros in each group can be omitted, and a consecutive sequence of all-zero groups can be compressed with :: (once per address):

2001:db8:85a3::8a2e:370:7334

The address space is 2¹²⁸ — roughly 3.4 × 10³⁸. To put that in perspective: you could assign more than 10²⁴ IPv6 addresses to every square meter of Earth's surface. NAT in IPv6 is unnecessary and, by design, not recommended — every device can have a globally routable public address. The end-to-end connectivity that NAT destroyed in IPv4 is restored.

IPv6 address types

Prefix Type IPv4 equivalent
::1/128 Loopback 127.0.0.1
fe80::/10 Link-local (auto-configured) 169.254.x.x
fc00::/7 Unique Local (ULA, private network) RFC 1918
2000::/3 Global unicast (public IP) Public IPs

The link-local address (fe80::) is auto-configured on every active IPv6 interface — no DHCP, no manual configuration. It's sufficient for communication within the same local network segment.


Why IPv6 adoption is still incomplete

IPv6 was specified in 1998. In 2026, global adoption sits around 40–50% depending on the metric. Brazil was approaching 50% in 2024. The obvious question is: why did it take this long?

Three main reasons:

1. IPv4 and IPv6 are not compatible. An IPv4-only host cannot communicate with an IPv6-only host without some transition mechanism. This means enabling IPv6 doesn't turn off IPv4 — you run dual-stack for an indefinite period, maintaining two stacks to manage, monitor, and debug.

2. NAT "solved" the urgent problem. As long as the IPv4 secondary market and CGNAT kept the internet functional, the pressure to migrate decreased. Migration has cost; a "solved" problem has no urgency.

3. Inconsistent support in legacy equipment. Old routers, decade-old corporate firewalls, embedded systems — parts of the infrastructure simply didn't support IPv6 without hardware replacement.

What accelerated adoption in recent years was pressure from hyperscalers and mobile ISPs. Google, Facebook, and other large players enabled IPv6 years ago. Mobile operators (who never had enough IPv4 addresses for their smartphone base) adopted IPv6 faster than fixed-line providers.


Technical differences that matter day-to-day

Beyond addressing, IPv6 introduced protocol changes with practical impact:

Simplified header: the IPv4 header has variable length (due to Options) and includes a checksum. The IPv6 header is fixed at 40 bytes, has no checksum (delegated to upper layers), and extends via optional extension headers. This makes line-rate processing easier for routers.

SLAAC (Stateless Address Autoconfiguration): in IPv6, a device can configure its own global address without DHCP, using the prefix announced by the router and a locally derived identifier. DHCPv6 exists, but it's not mandatory.

Native IPsec: IPv6 was designed with IPsec as an integral part, not an optional extension as in IPv4. In practice, use is still optional, but support is mandatory in compliant implementations.

No broadcast: IPv6 uses multicast where IPv4 would use broadcast. ff02::1 is the equivalent of 255.255.255.255 — but it's multicast to all nodes on the link, not a blind flood.


Practical implications for code

Bind on 0.0.0.0 vs ::. If you start a server binding to 0.0.0.0, you're listening on all IPv4 interfaces. To listen on IPv6, you bind to ::. Most modern operating systems configure IPv6 sockets with IPV6_V6ONLY by default — a socket on :: won't automatically accept IPv4 connections. Check whether your application binds explicitly to both protocols or whether your framework handles it.

Address parsing. If you store IPs in a database, IPv4 fits in a 32-bit integer or 4 bytes. IPv6 needs 128 bits — 16 bytes. PostgreSQL has the inet type that supports both. If you use VARCHAR, you'll need at least 39 characters for an expanded IPv6 address. And if you're doing manual regex parsing for IPv4, you'll need to rewrite it to handle IPv6.

Logs and metrics. Systems that parse logs to extract IPs need to handle IPv6. An address like ::ffff:192.0.2.1 is an IPv4-mapped IPv6 address — IPv6 wrapping an IPv4, common when an IPv6 socket receives an IPv4 connection.

To inspect which public IP a system is seeing, the ISP, the ASN, and whether the connection came in via IPv4 or IPv6, I use IP Address Info — particularly useful when debugging dual-stack behavior and you want to confirm which protocol is actually being used.


Frequently asked questions

Why does my IP start with 192.168 or 10.x?

Those are private addresses (RFC 1918) — not routable on the public internet. That's the IP your router assigned to your device on the local network. The IP the world sees is the public IP of your router, assigned by your ISP. To see the public IP, you need to ask an external server.

Is IPv6 faster than IPv4?

Not inherently. Connection speed depends on the infrastructure between origin and destination, not the addressing protocol. In some scenarios, IPv6 can be marginally more efficient due to the simplified header and the absence of NAT (which adds latency and state on routers), but the difference is negligible in most practical cases.

Does my site need to support IPv6?

Depends on your audience. If a significant portion of your users is on mobile (especially in countries with high IPv6 adoption), they may be arriving via IPv6. If your server only listens on IPv4, most modern clients will automatically fall back (Happy Eyeballs / RFC 6555), but with a small delay. For dual-stack hosting, most cloud providers already offer IPv6 — it's a network configuration, not an application code change.

Why does IPv4 still exist if IPv6 is better?

Because migration has cost and IPv4 still works. CGNAT solved the address problem well enough to remove urgency. IPv6 will eventually dominate — but "eventually" in network infrastructure is measured in decades.


Exhaustion solved, complexity increased

IPv4 lasted longer than it should have because of NAT — a solution that worked but broke the original internet model where every host has a unique, globally routable address. IPv6 restores that model with room to spare, but it arrived late enough to find decades of infrastructure, code, and operations built around IPv4.

The current dual-stack state is the result: two versions of the protocol coexisting indefinitely, with all the operational cost that implies. For anyone writing distributed systems, the minimum is ensuring your code handles IPv6 addresses correctly — both in server bind calls and in the storage and parsing of IPs that show up in your logs.


Note: the editorial content ends here. What follows is a pointer to a related tool.


To see which public IP is being used on a connection — IPv4 or IPv6 — along with ISP, ASN, and approximate location, IP Address Info shows that data in real time in the browser. Useful for confirming which protocol a dual-stack connection is actually using.

RD
Author
Rafael Duarte
Desenvolvedor backend com passagem por fintech e SaaS B2B — trabalhou em times que escalaram APIs de zero a milhões de requisições. Carrega cicatrizes de produção suficientes para ter opiniões fortes sobre ferramentas, padrões e decisões de arquitetura. Não é acadêmico: leu a RFC do UUID quando precisou escolher entre v4 e v7 para uma tabela de alta escrita.
View profile