Networking Interview Prep
IP Addressing

IPv6

The Future of Addressing

LinkedIn Hook

IPv4 gave us 4.3 billion addresses. We ran out.

The world now has more internet-connected devices than people. Your smartphone, your laptop, your smart TV, your router, your watch, the server that delivered this post — each one needs an address. IPv4 cannot keep up.

IPv6 was designed to solve this permanently:

  • 340 undecillion addresses — that is 340,000,000,000,000,000,000,000,000,000,000,000,000 — more than enough for every grain of sand on Earth to have billions of addresses
  • Written in hexadecimal, not decimal — 2001:0db8:85a3::8a2e:0370:7334
  • No NAT required — every device can have a globally unique, publicly routable address
  • Built-in security — IPSec is mandatory in the IPv6 spec (optional in IPv4)

You will encounter IPv6 in cloud deployments, Docker networks, and any infrastructure running at scale. The dual-stack world where both IPv4 and IPv6 coexist is already here.

This lesson explains exactly how IPv6 addresses work, how to read them, and what the different address types mean.

Full lesson → [link]

#Networking #IPv6 #BackendEngineering #SystemDesign #InterviewPrep


IPv6 thumbnail


What You'll Learn

  • Why IPv4 exhaustion happened and why IPv6 was designed the way it is
  • How to read and write IPv6 addresses (hex groups, :: abbreviation, leading zero drop)
  • The three main IPv6 address types: unicast, multicast, and anycast
  • What link-local, global unicast, and loopback addresses look like in IPv6
  • What dual stack means and why we are in a transition period

The Analogy That Makes This Click

Think of IPv4 as a city built in the 1950s — it was designed for cars, families, and small neighborhoods. The roads worked well. Then the population exploded, cars multiplied, and suddenly every street is gridlocked because there simply are not enough road lanes or parking spaces.

IPv6 is the city rebuilt from scratch with modern infrastructure — wider highways, more intersections, room for billions more vehicles. The old city still runs alongside it (dual stack — both IPv4 and IPv6 operating simultaneously), but new construction goes on the IPv6 side.

The address format looks intimidating at first. But once you understand the structure — 8 groups of 16 bits in hex — it is just a bigger number written differently.


Why IPv4 Exhausted

IPv4 has 2³² ≈ 4.3 billion addresses. Sounds enormous. But:

  • Large address blocks were handed out generously in the early internet — MIT owns the entire 18.0.0.0/8 block (16 million addresses)
  • IoT exploded: thermostats, cameras, sensors, wearables — each wants a unique address
  • Mobile networks: billions of smartphones came online
  • Cloud providers: a single AWS region needs hundreds of thousands of addresses

IANA (Internet Assigned Numbers Authority) exhausted its last unallocated IPv4 blocks in February 2011. Regional registries followed. Today, IPv4 addresses are a finite resource auctioned on secondary markets for significant money. NAT has kept IPv4 alive longer than expected, but at a cost: complexity, connection state, broken end-to-end connectivity.


The IPv6 Address Format

An IPv6 address is 128 bits — four times longer than IPv4's 32 bits.

2¹²⁸ = 340,282,366,920,938,463,463,374,607,431,768,211,456

That is 340 undecillion. For context: there are roughly 7.5 × 10¹⁸ grains of sand on Earth. IPv6 could give every grain of sand a trillion unique addresses and still have room left.

The Full Format

IPv6 is written as 8 groups of 4 hexadecimal digits, separated by colons:

2001:0db8:85a3:0000:0000:8a2e:0370:7334
│    │    │    │    │    │    │    │
└─ 8 groups × 16 bits each = 128 bits total

Each hex digit represents 4 bits. 4 hex digits = 16 bits = one group. 8 groups × 16 bits = 128 bits.

Abbreviation Rule 1 — Drop Leading Zeros

Within any group, leading zeros can be dropped:

0db8  →  db8
0000  →  0
0370  →  370

Applying this:

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

Abbreviation Rule 2 — Collapse Consecutive All-Zero Groups with ::

A single run of one or more all-zero groups can be replaced with ::. The :: can only appear once in an address (otherwise the address is ambiguous).

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

The :: replaced two zero groups (0:0). To expand back, you count the groups present, calculate how many are missing, and fill them in with zeros.


IPv6 Address Types

1. Global Unicast — The Internet Addresses

These are the public, globally routable IPv6 addresses — the equivalent of public IPv4 addresses. They currently start with 2001: or other 2xxx: or 3xxx: prefixes.

2001:0db8:85a3::8a2e:0370:7334   ← a typical global unicast address

The 2001:db8::/32 range is specifically reserved for documentation examples — you will see it everywhere in textbooks and RFCs. It is never used in production.

Every IPv6-enabled interface automatically generates a link-local address starting with fe80::. These addresses are used for communication within a single network link — the same subnet — without any configuration. No DHCP, no manual assignment.

fe80::1%eth0   ← link-local address on the eth0 interface

The %eth0 suffix (zone ID) is required when using link-local addresses because the same address prefix (fe80::) appears on every interface — the zone ID disambiguates which interface to use.

Link-local addresses are the IPv6 equivalent of APIPA in IPv4, but they are not a fallback — they are always present and have a defined purpose (neighbor discovery, router discovery).

3. Loopback — ::1

IPv6 loopback is ::1 — a single address (not an entire /8 block like IPv4's 127.0.0.0/8). A packet sent to ::1 loops back to the local machine.

ping6 ::1          # ping loopback on Linux/Mac
curl http://[::1]:3000  # connect to local server via IPv6 loopback

Note: IPv6 addresses in URLs must be enclosed in brackets to avoid ambiguity with the port separator colon.

4. Multicast

IPv6 multicast starts with ff. One-to-many delivery — a packet is sent to a group address and delivered to all devices that have joined that multicast group.

ff02::1   ← all nodes on the local link (all IPv6 devices on the LAN)
ff02::2   ← all routers on the local link

IPv6 has no broadcast. The IPv4 255.255.255.255 concept does not exist in IPv6. Instead, multicast fulfills all the use cases that broadcast handled in IPv4 — more efficiently, because only interested devices receive multicast packets.

5. Anycast

An anycast address is assigned to multiple devices simultaneously. A packet sent to an anycast address is delivered to the nearest device with that address (as determined by routing). Anycast is used for load balancing and high availability.

Google's 8.8.8.8 DNS is actually anycast — your request goes to the nearest Google DNS server, not a specific machine.


IPv6 Address Structure

A global unicast IPv6 address has three logical parts:

| Global Routing Prefix | Subnet ID | Interface ID |
|       48 bits         |  16 bits  |   64 bits    |

Example: 2001:0db8:85a3 : 0001 : 0000:8a2e:0370:7334
         ─────────────── ──────  ─────────────────────
         Routing prefix  Subnet  Interface ID (host)
  • Global Routing Prefix (48 bits): Assigned by your ISP or regional registry. Identifies your organization's address block.
  • Subnet ID (16 bits): Used internally to divide the organization's block into subnets. 16 bits = 65,536 subnets.
  • Interface ID (64 bits): Identifies a specific interface on a device. Often derived from the MAC address via a process called EUI-64.

EUI-64 — Auto-Generated Interface IDs

Devices can generate their own interface ID from their MAC address using EUI-64:

  1. Take the 48-bit MAC address: AA:BB:CC:DD:EE:FF
  2. Insert FF:FE in the middle: AA:BB:CC:FF:FE:DD:EE:FF
  3. Flip the 7th bit of the first byte: A8:BB:CC:FF:FE:DD:EE:FF
  4. This becomes the 64-bit Interface ID

This means devices can configure their own IPv6 addresses without DHCP — a feature called SLAAC (Stateless Address Autoconfiguration).


Dual Stack

The internet is currently in a dual stack transition — most infrastructure runs both IPv4 and IPv6 simultaneously. A dual stack host has both a 192.168.x.x (or similar) IPv4 address and a 2001:xxx:: IPv6 address.

When a dual stack host connects to a website:

  1. DNS returns both an A record (IPv4) and an AAAA record (IPv6)
  2. The OS uses an algorithm called Happy Eyeballs (RFC 8305) to try both simultaneously
  3. Whichever connects faster is used — typically IPv6 if available
  4. If IPv6 fails, the connection falls back to IPv4

As a developer, you should test your applications on both protocols. A server listening only on 0.0.0.0 (IPv4 wildcard) will not accept IPv6 connections — you need to also bind to :: (IPv6 wildcard).


Code Example 1 — IPv6 Address Parser and Expander

// IPv6 address utilities: expand, validate, and classify

function expandIPv6(address) {
  // Remove zone ID if present (e.g., fe80::1%eth0 → fe80::1)
  address = address.split("%")[0].toLowerCase();

  // Handle embedded IPv4 (simplified — not handled here)
  // Expand :: notation
  if (address.includes("::")) {
    const parts = address.split("::");
    const left  = parts[0] ? parts[0].split(":") : [];
    const right = parts[1] ? parts[1].split(":") : [];
    const missing = 8 - left.length - right.length;
    const middle = Array(missing).fill("0000");
    const full = [...left, ...middle, ...right];
    return full.map(g => g.padStart(4, "0")).join(":");
  }

  // Already fully expanded (or just needs padding)
  return address.split(":").map(g => g.padStart(4, "0")).join(":");
}

function compressIPv6(address) {
  const expanded = expandIPv6(address);
  const groups   = expanded.split(":");

  // Drop leading zeros in each group
  const shortened = groups.map(g => g.replace(/^0+/, "") || "0");

  // Find the longest run of consecutive "0" groups
  let bestStart = -1, bestLen = 0;
  let start = -1, len = 0;
  for (let i = 0; i <= shortened.length; i++) {
    if (shortened[i] === "0") {
      if (start === -1) { start = i; len = 0; }
      len++;
    } else {
      if (len > bestLen) { bestStart = start; bestLen = len; }
      start = -1; len = 0;
    }
  }

  if (bestLen < 2) return shortened.join(":");  // no useful compression

  const left  = shortened.slice(0, bestStart).join(":");
  const right = shortened.slice(bestStart + bestLen).join(":");

  if (!left && !right) return "::";
  if (!left)  return `::${right}`;
  if (!right) return `${left}::`;
  return `${left}::${right}`;
}

function classifyIPv6(address) {
  const expanded = expandIPv6(address);
  const prefix   = expanded.replace(/:/g, "");

  if (expanded === "0000:0000:0000:0000:0000:0000:0000:0001") return "Loopback (::1)";
  if (expanded.startsWith("fe80"))    return "Link-Local (fe80::/10)";
  if (expanded.startsWith("ff"))      return "Multicast (ff00::/8)";
  if (expanded.startsWith("fc") || expanded.startsWith("fd")) return "Unique Local (fc00::/7)";
  if (expanded.startsWith("2001:0db8")) return "Documentation range (2001:db8::/32) — not routable";
  if (/^[23]/.test(expanded))         return "Global Unicast";
  if (expanded === "0000:0000:0000:0000:0000:0000:0000:0000") return "Unspecified (::)";
  return "Unknown";
}

// === Demo ===
const addresses = [
  "2001:0db8:85a3:0000:0000:8a2e:0370:7334",
  "fe80::1",
  "::1",
  "ff02::1",
  "2001:db8::8a2e:370:7334",
];

for (const addr of addresses) {
  const expanded   = expandIPv6(addr);
  const compressed = compressIPv6(addr);
  const type       = classifyIPv6(addr);

  console.log(`\nInput:      ${addr}`);
  console.log(`Expanded:   ${expanded}`);
  console.log(`Compressed: ${compressed}`);
  console.log(`Type:       ${type}`);
}

What this shows:

  • :: expansion fills in the missing zero groups to reconstruct the full 128-bit address
  • Compression is the reverse: find the longest zero run and collapse it
  • Address type is determined by the prefix — just like IPv4 special ranges

Code Example 2 — Dual Stack Server (Node.js)

This example shows how to run a server that accepts both IPv4 and IPv6 connections.

const http = require("http");
const os   = require("os");

// Bind to :: (IPv6 wildcard) — accepts both IPv6 and IPv4-mapped IPv6 connections
// On most systems, binding to :: also accepts IPv4 via IPv4-mapped addresses (::ffff:x.x.x.x)
const server = http.createServer((req, res) => {
  const clientIP = req.socket.remoteAddress;
  const family   = req.socket.remoteFamily; // 'IPv4' or 'IPv6'

  // IPv4-mapped IPv6 address: "::ffff:192.168.1.5" — strip the prefix for display
  const displayIP = clientIP.startsWith("::ffff:")
    ? `${clientIP.replace("::ffff:", "")} (IPv4-mapped via IPv6 socket)`
    : clientIP;

  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end(`Hello! You connected via ${family}\nYour IP: ${displayIP}\n`);
});

// Listen on :: to accept both IPv4 and IPv6
server.listen(3000, "::", () => {
  const interfaces = os.networkInterfaces();

  console.log("Server listening on port 3000");
  console.log("\nLocal addresses:");
  for (const [name, addrs] of Object.entries(interfaces)) {
    for (const addr of addrs) {
      if (!addr.internal) {
        console.log(`  [${addr.family}] ${addr.address} (${name})`);
      }
    }
  }
  console.log("\nTest commands:");
  console.log("  curl http://127.0.0.1:3000        ← IPv4");
  console.log("  curl http://[::1]:3000             ← IPv6 loopback");
  console.log("  curl http://localhost:3000          ← resolved by OS (usually IPv4)");
});

What this shows:

  • Binding to :: (IPv6 wildcard) is the dual stack equivalent of 0.0.0.0 for IPv4
  • IPv4 connections arrive as IPv4-mapped IPv6 addresses: ::ffff:192.168.1.1
  • IPv6 addresses in URLs always go in square brackets: http://[::1]:3000
  • req.socket.remoteFamily tells you which protocol the client actually used

IPv6 visual 1


Common Mistakes

Mistake 1 — Placing :: in more than one location

:: can only appear once in an IPv6 address. If you write 2001::85a3::7334, it is ambiguous — there is no way to know how many zeros belong to each ::. This is a parse error. If you need to collapse multiple non-contiguous zero groups, you can only collapse the longest run with :: and must write the others explicitly as 0.

Mistake 2 — Forgetting square brackets in IPv6 URLs

The colon in an IPv6 address conflicts with the colon that separates host from port in a URL. Always wrap IPv6 addresses in square brackets: http://[2001:db8::1]:8080. Without brackets, the URL parser will misread the address. curl http://::1:3000 will fail; curl http://[::1]:3000 will work.

Mistake 3 — Thinking IPv6 eliminates NAT

IPv6 was designed to make NAT unnecessary — every device gets a globally unique address. In theory, you should be able to reach any device directly by its IPv6 address. In practice, many organizations still run IPv6 behind firewalls with NAT66 (IPv6-to-IPv6 NAT) for policy reasons. IPv6 does not eliminate the need for firewalls. The security boundary still exists — but the mechanism is a stateful firewall rather than address translation.


Interview Questions

Q: Why was IPv6 created?

IPv4 has a 32-bit address space — approximately 4.3 billion unique addresses. With the explosion of internet-connected devices (smartphones, IoT, cloud servers), IPv4 addresses were exhausted. IANA handed out its last unallocated blocks in 2011. IPv6 uses a 128-bit address space, providing 340 undecillion addresses — enough for every device for the foreseeable future. IPv6 also improves on IPv4 by eliminating broadcast, making IPSec mandatory, simplifying the header format, and enabling SLAAC (stateless address autoconfiguration).

Q: How do you compress an IPv6 address?

Two rules apply. First, within any group, leading zeros can be dropped: 0db8 becomes db8, 0000 becomes 0. Second, one contiguous run of all-zero groups can be replaced with ::. For example, 2001:0db8:0000:0000:0000:0000:0370:7334 compresses to 2001:db8::370:7334. The :: can only appear once — if there are multiple zero runs, collapse only the longest one.

Q: What is the difference between unicast, multicast, and anycast?

Unicast delivers a packet to one specific destination. Multicast delivers a packet to a group of devices that have subscribed to a multicast address — IPv6 uses multicast extensively (starting with ff) as a replacement for IPv4 broadcast. Anycast assigns the same address to multiple devices; a packet is delivered to the topologically nearest one. Anycast is used for load balancing and redundancy (e.g., DNS root servers, CDN edge nodes) — the sender does not know which specific server will receive the packet, only that the closest one will.

Q: What is a link-local IPv6 address and when is it used?

A link-local address starts with fe80:: and is automatically configured on every IPv6 interface without any configuration or DHCP. It is valid only on a single network link — packets with link-local source or destination addresses are never forwarded by routers. Link-local addresses are used for neighbor discovery (finding other devices on the same subnet), router discovery (finding the default gateway), and SLAAC (stateless address autoconfiguration). They are always present alongside any global unicast addresses the interface may have.


Quick Reference — Cheat Sheet

ConceptValueNotes
IPv6 size128 bits8 groups of 16 bits, hex
Total addresses340 undecillion2¹²⁸
Format2001:db8::1Colon-separated hex groups
Loopback::1Equivalent to IPv4 127.0.0.1
Unspecified::Equivalent to IPv4 0.0.0.0
Link-local prefixfe80::/10Auto-assigned, not routed
Global unicast2000::/3Publicly routable
Multicast prefixff00::/8Replaces IPv4 broadcast
Documentation range2001:db8::/32Examples/testing only
Unique localfc00::/7Private (like RFC 1918)
:: ruleCollapse one zero runCannot appear twice
Leading zero drop0db8db8Per group
URL formathttp://[::1]:8080Brackets required
Dual stackBoth IPv4 + IPv6Transition mechanism
IPv6 wildcard::Equivalent to IPv4 0.0.0.0
SLAACNo DHCP neededInterface ID from MAC (EUI-64)

Previous: Lesson 3.1 — IPv4 — How Internet Addressing Works → Next: Lesson 3.3 — IPv4 vs IPv6 Comparison →


This is Lesson 3.2 of the Networking Interview Prep Course — 8 chapters, 32 lessons.

On this page