Tag Archives: EKS networking

VPC Lattice: What It Actually Replaces, What It Costs, and When I’d Reach for It

AWS App Mesh shuts down on September 30, 2026. Not “enters maintenance mode” — the console and the resources stop working. If you’re one of the teams that bet on it in 2019 for EKS service-to-service traffic, you’ve got a couple of months left, and AWS has been pointing everyone at the same replacement for ECS workloads and EKS workloads alike: Amazon VPC Lattice.

That deadline is a decent excuse to actually understand what Lattice is, because it’s not just an App Mesh clone. It quietly replaces a chunk of what Transit Gateway and PrivateLink do too, and it changes some assumptions network engineers have had baked in since VPC peering existed. Worth twenty minutes even if you have no App Mesh to migrate.

What VPC Lattice actually is

Strip away the marketing and VPC Lattice is a managed, regional application-layer proxy that sits between your consumers and your services, handles service discovery, applies IAM-based authorization, and routes requests — all without you deploying a load balancer, a sidecar, or a peering connection. AWS’s own description is that it manages network connectivity and application layer routing between services across different VPCs and AWS accounts, and that’s a fair summary, if a little dry.

The mental model that clicked for me: think of it as a load balancer that doesn’t live in any one VPC. You publish a service into a service network (a logical boundary, not a piece of infrastructure you provision), and any VPC or account associated with that service network can reach it by DNS name — no route tables, no CIDR planning, no peering mesh growing into an unmanageable tangle.

Lattice Service Network.

A service network can span accounts via AWS Resource Access Manager, so a platform team can own the network and share it out to application teams without those teams ever touching a route table. That’s the part that made this interesting to me as an architect rather than as a networking hobbyist — it moves network topology out of the app team’s problem space entirely.

What it’s quietly replacing

Nobody built this in a vacuum. Every one of these had a gap Lattice was built to close.

VPC peering doesn’t scale past a certain account count — it’s point-to-point, so N accounts means something close to N² connections, and overlapping CIDRs break it outright. Lattice’s data plane assigns consumers a link-local address and doesn’t care what your VPC CIDR looks like, overlapping or not.

Transit Gateway solved the peering-mesh problem at layer 3/4 — it’s still the right tool for routing IP traffic between VPCs and on-premises networks at scale, and I wouldn’t rip one out to replace it with Lattice. But TGW has no concept of an HTTP request, a path, or an identity. It moves packets, not requests. If your actual problem is “service A needs to call /v2/orders on service B and I want to enforce that with IAM,” TGW can’t help you get there on its own.

AWS PrivateLink is the closest sibling — it’s also a proxy-based, non-peering way to expose a service across accounts. The difference is PrivateLink is fundamentally point-to-point: each consumer VPC needs its own interface endpoint, and there’s no native request-level routing or IAM authorization baked into the data path. Lattice centralizes that into one service network that many consumers attach to, and layers on HTTP-aware routing rules on top.

AWS App Mesh is the one with the deadline. It gave you real service-mesh features — client-side retries, circuit breaking, fine control — but it did that with an Envoy sidecar next to every task, which is real operational weight: certificate rotation, sidecar upgrades, resource overhead per pod. Lattice deliberately drops the sidecar. You lose some of App Mesh’s client-side sophistication in the trade — Lattice’s routing and auth decisions happen server-side, not in a proxy next to your code — but for most teams that’s a fair trade for not operating a mesh control plane.

VPC PeeringTransit GatewayPrivateLinkVPC Lattice
OSI layerL3L3/L4L3/L4L7 (app layer)
Cross-account model1:1 meshHub-and-spoke1:1 endpoint per consumerMany-to-many via service network
CIDR overlap tolerantNoNoYesYes
Identity-aware authNoNoNo (SG/NACL only)Yes (IAM/SigV4)
Request-level routingNoNoNoYes (path, method, header, weighted)
Sidecars requiredNoNoNoNo

How it’s actually built

Four concepts do the work. A service is the logical front door — listeners, rules, target groups — conceptually a load balancer, but one that isn’t tied to a single VPC. A listener is a protocol and port (HTTP, HTTPS, or TLS_PASSTHROUGH). A rule matches on path, HTTP method, or header and forwards to a target group, which can hold EC2 instances, IP addresses, Lambda functions, or an Application Load Balancer, and — as of the more recent releases — ECS and Fargate tasks natively alongside EC2 and EKS.

Worth calling out explicitly: Lattice terminates HTTPS itself using an ACM-managed certificate, which is convenient, but it only does server-side TLS. If you need mutual TLS, you have to use a TLS_PASSTHROUGH listener and let the target negotiate the client certificate — Lattice’s own data plane won’t do mTLS termination for you.

The newer half of the story is VPC Resources and Resource Gateways, which let you expose non-HTTP TCP endpoints — a database, an internal domain name, an on-premises system reachable over Direct Connect or VPN — through the same service network model, complete with the same IAM controls. This is the part that pushes Lattice past “App Mesh replacement” and into “how do I expose an RDS instance to another account without a peering connection or a bastion.” It’s genuinely useful, and it’s the feature I’d bring up first if a platform team asked me why this deserves attention beyond the App Mesh deadline.

For Kubernetes specifically, the AWS Gateway API Controller implements the open-source Kubernetes Gateway API and translates Gateway and HTTPRoute objects into Lattice service network objects behind the scenes. If your EKS team already writes Gateway API manifests, adopting Lattice barely changes their workflow — it’s the controller that’s doing the AWS-specific work.

Authorization runs on IAM. Auth policies attached at the service network or service level use standard IAM policy JSON, and clients authenticate with SigV4-signed requests, the same signing scheme every other AWS API call uses. This is a genuine strength if your org already centers identity around IAM roles, and a genuine adoption cost if you have legacy clients that have never had to sign a request in their life. Budget time for that conversation — it comes up in almost every migration writeup I’ve read.

When I’d actually reach for it

When Lattice makes sense.

Lattice earns its place when the actual requirement is cross-account or cross-VPC service exposure with identity-aware access control and some request-level routing, and you don’t want to own a control plane to get it. New microservice builds, platform teams centralizing how application teams expose services to each other, EKS shops trying to get off App Mesh before the clock runs out, and anyone who’s been maintaining a PrivateLink endpoint-per-consumer sprawl are the clearest fits.

I’d think twice before using it as a wholesale Transit Gateway replacement. It’s not built for raw IP-layer routing at TGW’s scale, and — as I’ll get to in pricing — the per-service hourly charge adds up fast if you’re running hundreds of services with modest traffic each. I’d also pause if you need genuine client-side mesh behavior: retries with backoff, circuit breakers, fault injection for chaos testing. That logic sits server-side in Lattice, which is simpler to operate but less flexible than a sidecar that runs next to your code.

Pros and cons, plainly

The upside is real: no sidecars to patch, no peering mesh to keep untangled, IAM auth you already understand, weighted routing for blue/green and canary out of the box, and a service directory that gives you an actual inventory of what’s exposed to what. Observability is baked in too — access logs and CloudWatch metrics per service without instrumenting anything yourself.

The downside is mostly about maturity and rigidity. It’s newer than TGW or PrivateLink, so you’ll hit rough edges — G2 reviewers flag protocol support currently limited to HTTP, HTTPS, and gRPC, and region coverage, while it’s grown a lot since GA, still isn’t everywhere. Security group design has a real gotcha: targets need to allow inbound traffic from the Lattice association security group, not from the consumer’s VPC CIDR, and that trips people up in early deployments because it looks wrong at first glance. And moving to IAM/SigV4 auth is a genuine client-side change — nothing you can skip past.

Pricing — the part that actually decides adoption

Three dimensions drive the bill: an hourly charge per service, a per-GB data processing charge, and a per-request (or per-connection, for TLS_PASSTHROUGH) charge above a free tier. In US East (N. Virginia), that’s $0.025 per service-hour, $0.025 per GB processed, and $0.10 per million requests beyond the first 300,000 free per hour. Compare that to PrivateLink at roughly $0.01 per hour per AZ plus $0.01/GB with volume discounts, and it’s clear Lattice costs more per unit — you’re paying for the extra L7 intelligence and the simpler operating model, not for cheaper bytes.

Run the numbers on a single, modestly busy service and it’s not scary: one service processing 100 GB and 200,000 requests an hour for a month lands around $18–20 in hourly charges alone before data and requests, and a heavier example AWS publishes — one service with HTTPS and TLS listeners together processing 2,100 GB and millions of requests a month — comes out to roughly $268 a month. The bill gets serious at fleet scale. One cloud architect’s published comparison modeled 200 services across 100 accounts pushing 30TB a month: Transit Gateway came out around $4,250, Lattice around $4,840 — roughly a 14% premium, driven almost entirely by the per-service hourly charge rather than data processing, which was actually cheaper for TGW in that scenario. If you’re running that many low-traffic services, the fixed hourly cost per service matters more than the per-GB rate.

VPC Resources (the database/on-prem exposure feature) bill separately and use a tiered per-GB rate: $0.01/GB for the first petabyte in a Region each month, dropping to $0.006 and then $0.004/GB at higher volumes, plus a small hourly charge per resource. Worth modeling separately from your service traffic if you’re planning to route a lot of data through it.

Quotas worth knowing before you design around them

These are the ones that actually shape an architecture, not just trivia:

QuotaDefaultAdjustable
Services per Region2,000Yes
Service networks per Region50Yes
Service associations per service network500Yes
VPC associations per service network500Yes
Target groups per service10Yes
Targets per target group1,000Yes
Listeners per service2Yes
Rules per listener10Yes
Requests/sec per service per AZ10,000Contact your SA/TAM
Bandwidth per service per AZ10 GbpsContact your SA/TAM
Connection idle timeout (HTTP/gRPC)1 minuteContact your SA/TAM
Max connection lifetime10 minutesFixed
Service networks a VPC can associate with directly1— (use service-network VPC endpoints for more)

Full, current numbers are on the official quotas page — check it before you design, not after you hit a wall. The one that catches people off guard most is the one-service-network-per-VPC-via-direct-association limit; if you need a VPC in more than one service network, you’re routing through service-network VPC endpoints instead, which is an extra layer to plan for.

A few concrete use cases

A platform team centralizing how forty application teams expose internal APIs to each other, replacing forty sets of ad-hoc security-group rules and a slowly decaying peering mesh with one service network and a consistent IAM auth policy. A company running canary deployments where 5% of production traffic gets weighted onto a new service version before a full cutover — Lattice’s weighted target groups do this natively, no custom load balancer logic required. An EKS shop migrating off App Mesh before the September deadline, using the Gateway API Controller so app teams keep writing the same HTTPRoute manifests they already know. And the resource-gateway pattern: exposing a shared RDS instance in a data-platform account to a dozen consuming accounts without provisioning a PrivateLink endpoint in every one of them.

Why this belongs on your radar even without the App Mesh deadline

The App Mesh shutdown is the forcing function, but the more interesting shift is architectural: AWS is pulling network topology out of individual VPCs and into a service-oriented abstraction that’s owned centrally and consumed by reference. That’s a meaningful change to how you’d write a network architecture standard or review an ADR — the question stops being “how do these two VPCs route to each other” and starts being “which service network does this belong to, and what’s the IAM policy governing who can call it.” If you own architecture review or network standards for your org, that’s worth getting ahead of before it shows up in someone else’s design doc and you’re reviewing it cold.

It’s not a wholesale replacement for Transit Gateway, and it’s not free — budget the per-service hourly charge honestly before you commit a few hundred services to it. But for the specific problem it targets, cross-account and cross-VPC service exposure with identity-aware access control, it’s a cleaner answer than anything that came before it, and worth prototyping now rather than in month eleven of an App Mesh migration deadline.