Skip to content

Deploying IPv6-first EKS on AWS: what still doesn't work, and what it saves

Field notes for platform and network engineers considering an IPv6-first deployment on AWS. Written by the team that runs the isp6 platform. Last updated: July 2026.

Since 1 February 2024, AWS charges $0.005 per hour for every public IPv4 address, about $3.65 a month, per address, across every service. For a conventional three-AZ EKS setup that adds up quietly: NAT gateway EIPs, load balancer addresses, the odd bastion. The charge made IPv6-first architectures financially interesting for the first time.

We had an additional motive. isp6 is a RIPE NCC LIR whose entire product is making IPv6 adoption easy, so running our own platform on IPv4 would have been embarrassing. We built our order-management platform as IPv6-first EKS, with each environment's VPC carrying a /56 from our own PA allocation via BYOIPv6, the same journey our members take. Our VPCs do still support IPv4, in roughly the way an office still supports a fax machine: we originally allocated /28s, the smallest subnets AWS permits, purely to maintain connectivity with legacy networks.

This is a field report on whether AWS can actually deliver IPv6 end-to-end in 2026. Short version: mostly, now, with a specific and shrinking list of exceptions, and one of our /28s didn't survive contact with the enemy.

The thesis: you are only as IPv6 as your least-capable dependency

Nothing about IPv6 on AWS fails loudly. What happens instead is that one dependency (a database engine, a payment API, a container registry) quietly refuses to speak anything but IPv4, and to reach it you keep a NAT gateway, and to keep a NAT gateway you keep IPv4 routes, addresses, and its bill. The interesting question is never "does AWS support IPv6?" It is "which of my dependencies drags IPv4 back in, and what does each one cost me?"

Here is our dependency-by-dependency answer, with dates, because several of these were fixed mid-flight.

What we built

  • EKS with ipFamily: ipv6: pods and services get IPv6 only, via VPC CNI prefix delegation (a /80 per node, a /128 per pod). Every pod has a globally unique address from our own RIPE allocation. IP exhaustion maths, secondary CIDRs, and custom networking cease to exist as concepts.
  • Egress-only internet gateway as the default egress path: free, stateful, outbound-only, no per-GB processing charge, and the pod's own address is preserved (no SNAT).
  • A single NAT gateway: not three, kept only as the legacy fallback for IPv4-only destinations.
  • Dual-stack interface endpoints for the AWS APIs the cluster needs (ECR, STS, KMS, Secrets Manager, SSM), with a security group that admits only IPv6 on 443, so any client that resolves the A record fails closed.
  • Dual-stack ALBs at the edge, and CloudFront for static content.
  • No RDS on the primary data path: the database tier is a managed service reached over PrivateLink. More on why below.
An IPv6-first VPC with an EKS node hosting an IPv6-only pod, showing three egress paths: a free default path through an egress-only internet gateway to IPv6 destinations, a metered path through dual-stack interface endpoints to AWS service APIs, and a metered legacy fallback through a single NAT gateway to IPv4-only destinations.
Three ways out of an IPv6-first VPC. The design goal is to keep everything on the top path (free and NAT-less) and treat the bottom one as a shrinking legacy liability.

The gaps, dated

There is no such thing as an IPv6-only EKS cluster. ipFamily: ipv6 means pods and services are IPv6-only; the nodes remain dual-stack, and every subnet you give EKS must still carry an IPv4 CIDR. The choice is irreversible at cluster creation, Nitro instances only, no Windows pods, no Outposts, no FSx for Lustre, no custom networking. On top of that, the VPC CNI chains a host-local plugin that hands each pod a non-routable IPv4 address from 169.254.172.0/22 and SNATs it to the node's IPv4 when a pod talks to an IPv4-only destination. This interop shim is why IPv6 EKS "just works", and why you never fully escape IPv4: your v4-only dependencies don't crash, they just silently take the NAT path, and you discover them in flow logs rather than stack traces.

RDS still cannot run without IPv4, anywhere. IPv6-only subnets are unsupported, and dual-stack mode requires an IPv4 CIDR on every subnet in the DB subnet group. Progress is real but slow: publicly accessible dual-stack databases shipped 31 October 2025, and IPv6 for VPC endpoints of the RDS service APIs only landed 30 January 2026. The common escape hatch is running the database tier off RDS entirely, using a managed datastore reached over PrivateLink (MongoDB Atlas is the canonical example) precisely because of this. Be clear-eyed about what that buys, though: PrivateLink interface endpoints themselves still require IPv4 today, so the hatch relocates the constraint to a different layer rather than deleting it. And we're not exempt: we still run an RDS instance for an internal tool, and that single instance is enough to pin IPv4 CIDRs onto its subnets regardless. The dependency only has to appear once.

ECR was IPv4-only for years, fixed May 2025. This one improved while we were running. ECR gained dual-stack endpoints on 30 April 2025 and PrivateLink support for those dual-stack endpoints on 21 November 2025. Before that, every image pull on an "IPv6" cluster was quietly riding the CNI's IPv4 shim. Note that dual-stack remains opt-in: the default registry hostnames still resolve to IPv4.

The default AWS endpoint hostnames are an IPv4 trap. Checked July 2026: sts.eu-west-1.amazonaws.com has no AAAA record; sts.eu-west-1.api.aws does. The SDKs default to the former, and AWS_USE_DUALSTACK_ENDPOINT is not on by default. If you don't opt in per client, or force the issue with dual-stack VPC endpoints as we do, your "IPv6" workload's AWS API calls are IPv4.

CloudFront learned to fetch over IPv6 in September 2025, except from the origins most people use. IPv6 origins shipped 8 September 2025, explicitly excluding S3 and VPC origins. Our static sites are exactly that shape: CloudFront speaks IPv6 to viewers and IPv4 to the S3 bucket behind it.

Internet-facing ALBs burn public IPv4 unless you opt out. A dual-stack ALB holds a public IPv4 per AZ, each billed since February 2024. dualstack-without-public-ipv4 has existed since May 2024 and eliminates the charge. We deliberately don't use it: our customers are, almost by definition, people mid-transition to IPv6. Our rule is to spend IPv4 money only at the edge, where it buys reach, never inside the VPC, where it buys nothing.

An IPv6 client resolving AAAA records and a legacy IPv4 client resolving A records both reach a dual-stack application load balancer, which holds one billed public IPv4 address per availability zone; behind it, all targets are IPv6-only pods.
The edge is the one place we pay for public IPv4 on purpose: the ALB translates legacy IPv4 clients onto an IPv6-only backend.

Then there's the long tail, which is where the dream goes to die. We checked our external dependencies on 14 July 2026: api.stripe.com has no AAAA record. github.com has no AAAA record, in 2026. Our SMS gateway and both of our identity-verification vendors have no AAAA records, and two of them sit behind CloudFront distributions where enabling IPv6 is a checkbox they have not ticked. (Credit where due: gitlab.com and Docker Hub resolve AAAA just fine.) Amazon MQ has no IPv6 story either, which is one of the reasons we run RabbitMQ in-cluster as a StatefulSet instead. Every name on that list is a reason our single NAT gateway still exists.

What it saves

Reference setup: three AZs, HA, private nodes, one internet-facing ALB. Us-east-1 list prices, 730-hour month. Data transfer out is excluded, because it costs the same over both protocols. Pricing changes frequently; treat these as indicative and check the current VPC pricing.

Monthly cost Conventional IPv4/NAT IPv6-first
NAT gateways (3 × $0.045/h) $98.55 $0
NAT gateway EIPs (3 × $0.005/h) $10.95 $0
NAT processing (~500 GB × $0.045) $22.50 $0 (egress-only IGW)
ALB public IPv4 (3 × $0.005/h) $10.95 $0–11 (your choice)
Total per environment ≈ $143 ≈ $0–11

Now the caveat that keeps this honest: the ~$0 only holds if everything speaks IPv6. Every IPv4-only dependency puts you back on one of two meters. A kept NAT gateway is ~$36.50/month plus $0.045/GB even at low volume, though IPv6-first shrinks its blast radius: ours carries only the legacy long tail, so one non-HA gateway in one AZ is an acceptable risk instead of a three-AZ tax. Interface VPC endpoints are the other meter, at ~$7.30/AZ/month each plus $0.01/GB, and they multiply. Seven AWS-API endpoints across three AZs is ~$153/month, which comfortably rivals the NAT bill you were congratulating yourself for deleting. The saving is large but not automatic, and it improves every time AWS ships a dual-stack public endpoint you can reach for free through the egress-only IGW instead.

Gotchas we hit

  • The /28s didn't survive. We sized IPv4 subnets at /28 as a statement of intent. A /28 has 11 usable addresses after AWS reserves five, and dual-stack interface endpoint ENIs plus node primary ENIs ate them. We grew to /27 public and /26 private, grudgingly.
  • Dual-stack endpoints resolve to both A and AAAA, and Happy Eyeballs clients will happily take the A. We enforce IPv6 at the security group, with v6-only ingress on 443, so IPv4 attempts fail closed instead of silently succeeding. (ip_address_type = "ipv6" on an endpoint would be cleaner, but AWS only permits it on IPv6-only subnets, which EKS can't use.)
  • ipFamily is forever. Changing your mind means a new cluster and a workload migration.
  • Not every AWS API has caught up regionally: the ec2messages endpoint wouldn't accept an IPv6 address type in our region, so we run Session Manager on ssm + ssmmessages alone.
  • Managed add-on services lag the core. Amazon MQ's missing IPv6 support forced the self-hosted RabbitMQ decision more than any Kubernetes preference did.
  • Your observability must speak IPv6 on day one, because the failure mode of everything above is silence, not errors. NAT flow logs are how we found which dependencies were quietly on the v4 path.

Verdict: worth it in 2026?

Yes, with a precise scope. If you are greenfield, Linux-on-Nitro, Kubernetes-native, and your datastore either supports IPv6 or hides behind PrivateLink anyway, IPv6-first EKS is the correct default in 2026. The constraint list is finite, documented above, and visibly shrinking: ECR, CloudFront origins, public RDS, and the RDS service APIs all moved between April 2025 and January 2026. You save ~$130+ per environment per month at small scale, more at NAT-heavy scale, and you permanently exit the IPv4 scarcity-management business: no more custom networking, secondary CIDRs, or overlapping RFC 1918 peering archaeology. We came for the missing NAT bill; we stayed because address planning stopped being a job.

If you need Windows pods, Outposts, an RDS-centred architecture, or your revenue path runs through IPv4-only SaaS APIs, be honest with yourself: you will be running that NAT gateway regardless, so run a minimal dual-stack VPC and take the interop wins without the purity. The protocol doesn't award style points. But check the list again in a year. Every one of these gaps has a shorter life expectancy than your cluster.

Sources


This document is provided for informational purposes. Protocol specifications and cloud provider behaviour are subject to change. Consult the linked RFCs and vendor documentation for authoritative, up-to-date information before making architectural decisions.