AWS VPC Lattice Complete Guide - Service-to-Service Networking Across VPCs and Accounts
First Published:
Last Updated:
The reason a definitive guide is overdue: every team building microservices on AWS now hits the same crossroads — should we run a service mesh, expose every backend through PrivateLink, glue VPCs together with Transit Gateway, or adopt VPC Lattice? — and the answer depends on details that the marketing pages skim past. VPC Lattice removes the NLB requirement that PrivateLink imposes on providers, supports cross-VPC and cross-account connectivity without the CIDR coordination tax of TGW, terminates TLS at the data plane so callers do not need to manage certificates, and lets IAM be the authorization surface for service-to-service calls. Resource Configurations and Resource Gateways, both GA at re:Invent 2024, extend that surface to RDS instances and arbitrary IP / domain targets, which is what lets VPC Lattice replace many PrivateLink Endpoint Service deployments. This guide compares VPC Lattice to the alternatives, walks through Service Networks / Services / Listeners / Target Groups / Auth Policies in depth, and ends with field-tested architecture patterns and pitfalls.
Deeper background on the VPC endpoint layer that often sits next to VPC Lattice (Resource endpoints are themselves a VPC Lattice feature) is covered in AWS PrivateLink and VPC Endpoints Complete Guide - Interface, Gateway, and Resource Endpoint. For the broader CIDR-planning and routing-design context, see VPC Design Review Checklist - CIDR, Subnets, Transit Gateway. For service-name and concept terminology used throughout this article, refer to the AWS Networking Glossary.
Table of Contents
- 1. Introduction — The "service mesh on AWS" problem
- 2. What is VPC Lattice?
- 3. Core Concepts
- 4. VPC Lattice vs Alternatives
- 5. Listener and Routing
- 6. Auth Patterns
- 7. Resource Configuration and Resource Gateway
- 8. Architecture Patterns
- 9. Implementation Walkthrough — Console, CDK, and Terraform
- 10. Observability
- 11. Use Cases
- 12. Common Pitfalls — A Field Checklist
- 13. Frequently Asked Questions
- 14. Summary
- 15. References
1. Introduction — The "service mesh on AWS" problem
The microservice-architecture playbook usually arrives at the same question once the second VPC, the third account, or the fourth backend gets added: how do services in different VPCs, different accounts, or different teams call each other safely and discoverably? The traditional answers each carry a tax:- Transit Gateway (TGW) stitches VPCs together at L3 and forces CIDR planning to remain global. Two business units that independently chose
10.0.0.0/16must either renumber one of them or fall back to overlapping-CIDR workarounds (Private NAT Gateway, second-CIDR attachments). TGW also has no notion of "service identity" — every workload that has IP reachability can attempt a TCP handshake to any other workload, and you defend with security groups and NACLs. - PrivateLink (Interface VPC endpoints) is per-service, requires an NLB or GWLB on the provider side, multiplies the number of endpoints linearly with the number of services and consumer VPCs, and offers no L7 routing or path-based dispatch.
- AWS App Mesh (Envoy-based service mesh, deprecation announced for 2026-09-30) and Amazon ECS Service Connect are container-only. They do not natively span EC2, Lambda, or on-premises hosts, and Service Connect lives within an ECS cluster.
- Customer-managed Istio / Linkerd on EKS gives full mesh semantics but requires the team to operate the control plane, the sidecars, certificate rotation, mTLS, and the observability pipeline.
*.vpc-lattice-svcs.<region>.on.aws); and there is no CIDR coordination requirement because Lattice presents itself in each consumer VPC at a Lattice-owned link-local IP range, so overlapping CIDRs between provider and consumer VPCs are tolerated by design.This article unpacks the rest of the design in depth.
2. What is VPC Lattice?
Amazon VPC Lattice is a managed application networking service that connects, secures, and monitors services regardless of which VPC or AWS account they live in. The unit of consumption is a Service Network — a logical boundary that associates Services (the things being called) and VPCs (the places callers run) and applies cross-cutting policy (authentication, authorization, observability) to every call that flows through it.2.1 Positioning vs PrivateLink, Transit Gateway, and meshes
VPC Lattice is not a replacement for any single existing tool; it occupies a new layer that overlaps each of them differently:- vs Transit Gateway: TGW is L3; Lattice is L4 / L7. TGW connects every IP to every IP and relies on the network team to fence off who-can-reach-what at the route-table and SG layer. Lattice connects services and relies on IAM to fence off who-can-call-what. The two coexist: many production setups run TGW for legacy and bulk traffic, Lattice for new service-to-service flows.
- vs PrivateLink (Interface endpoint to your own service): PrivateLink requires the provider to run an NLB, allow-lists consumer principals one at a time, and exposes a single backend per endpoint. Lattice removes the NLB, replaces the principal allow-list with IAM authorization, and lets one Service Network associate dozens of Services with dozens of consumer VPCs.
- vs App Mesh / Service Connect / Istio: Lattice has no sidecar. Routing and authorization happen in the managed data plane, so the application sees a normal HTTP socket. This is the same design direction App Mesh deprecated toward; Lattice is AWS's strategic successor for L7 service-to-service traffic that needs to span beyond a single cluster.
- vs API Gateway / ALB: API Gateway and ALB are north-south entry points (internet-facing or VPC-internal). Lattice is east-west (service-to-service, inside the AWS network).
2.2 What Lattice supports today
- Protocols: HTTP/1.1 on HTTP listeners; HTTP/1.1, HTTP/2, and gRPC on HTTPS listeners (HTTP version negotiated via ALPN, defaulting to HTTP/1.1 when ALPN is absent); and TLS passthrough via the Listener
TLS_PASSTHROUGHprotocol option (the AWS console labels this as "TLS listener"). - Target types: Instance (EC2), IP, Lambda, Application Load Balancer, and (via Resource Configuration) RDS DB instance / cluster, arbitrary IP-and-port, or arbitrary domain.
- Authentication and authorization:
NONE(open) orAWS_IAM(Sigv4-signed requests, evaluated against the Service's Auth Policy and any Service-Network-level Auth Policy). - Cross-Account: Service Networks and Services are both shareable via AWS RAM. A Service Network in account A can be associated with VPCs from account B once the RAM share is accepted.
- DNS: Lattice provides a managed regional DNS name per Service in the format
<service-name>-<service-id>.<service-network-id>.vpc-lattice-svcs.<region>.on.aws(for example,orders-02031c045478f6ddf1.7d67968.vpc-lattice-svcs.us-west-2.on.aws) and optionally a custom domain name fronted by an ACM-issued certificate. The generated name resolves to a Lattice-owned IPv4 link-local address in169.254.171.0/24(and an IPv6 unique-local address infd00:ec2:80::/64) inside each associated consumer VPC.
2.3 What Lattice does not do (yet)
- No cross-Region service network. A Service Network is regional; cross-Region calls travel either over TGW peering, PrivateLink cross-Region (where supported), or the public internet.
- No native WebSocket termination beyond what HTTP/1.1 Upgrade allows through a
TLS_PASSTHROUGHlistener. - No mTLS termination at the data plane. Lattice terminates server TLS but does not request a client certificate; mTLS must be handled by the target itself (and in that case the listener should be
TLS_PASSTHROUGH). - No multicast or UDP.
3. Core Concepts
The Lattice data plane is built from a small set of primary objects. The mental model is: a Service Network is a policy boundary; Services are backends; Listeners are front doors on a Service; Rules dispatch requests; Target Groups receive them; and Auth Policies decide whether the call is allowed.
3.1 Service Network
A Service Network is the top-level container. Two kinds of associations live on it:- Service association — attaches a Service to the network. Once associated, every VPC associated with this network can call the Service.
- VPC association — registers a VPC as a consumer of the network. The VPC gets Lattice-managed ENIs (one per associated subnet / AZ), routing for the Lattice link-local range, and managed private DNS resolution that maps the Service DNS names to those ENIs (handled by the VPC's default DNS resolver against a Lattice-managed zone — no Route 53 Resolver rule is required).
A Service Network can also carry a default access log subscription that routes access logs to CloudWatch Logs, S3, or Kinesis Data Firehose for every Service in the network.
3.2 Service
A Service is the backend abstraction. Each Service has:- Auth Type (
NONEorAWS_IAM). - Auth Policy (when
AWS_IAM). - Custom domain name + ACM certificate (optional).
- One or more Listeners.
- Logging configuration (independent of the Service Network's default).
3.3 Listener
A Listener is the entry port + protocol combination on a Service. Supported protocols areHTTP, HTTPS, and TLS_PASSTHROUGH. Each Listener carries an ordered list of Rules that examine the request and dispatch to a Target Group. The default rule is always required and acts as the catch-all.A common configuration is a single
HTTPS:443 listener with a custom domain (api.example.internal) and an ACM certificate; clients call by DNS name and the data plane terminates TLS. Listener limits and per-Service caps are tracked on the VPC Lattice quotas page; verify the current numbers there rather than memorizing them.3.4 Rule
A Rule matches a request and forwards it to one Target Group (with optional weighted action across multiple groups). Match conditions are:- HTTP method (
GET,POST, …). - Path (exact, prefix, or
pathmatch). - Header (presence or value match).
- Priority (1–100; lower wins).
POST /orders to a Lambda Target Group and GET /orders/{id} to an EC2 Instance Target Group, for example).3.5 Target Group
A Target Group holds one or more targets of a single type. Supported types:- Instance — EC2 instances by instance ID. Must live in a VPC that is associated with the same Service Network (or in the Service's own VPC for direct Service-to-Target binding).
- IP — arbitrary IPv4 or IPv6 addresses. Useful for on-premises hosts reached via DX, or for ECS tasks in
awsvpcmode. - Lambda — a Lambda function. The Service invokes the function with a Lattice-formatted event.
- ALB — an Application Load Balancer (typically used to keep an existing ALB-fronted service in place while clients migrate to Lattice).
3.6 Auth Policy
An Auth Policy is an IAM resource policy attached either to a Service Network or to a Service. Its structure is the familiarStatement / Effect / Principal / Action / Resource / Condition JSON. The unique aspects:- Action is always
vpc-lattice-svcs:Invoke— the single data-plane action for HTTP, HTTPS, andTLS_PASSTHROUGHrequests. Both the resource-based Auth Policy and the caller's IAM identity policy must reference this action. - Principal can be an AWS account, an IAM role / user, an organization (via
aws:PrincipalOrgID), or*(gated by network policy and IAM identity-based policy). - Condition keys unique to Lattice include
vpc-lattice-svcs:RequestMethod,vpc-lattice-svcs:RequestPath,vpc-lattice-svcs:RequestHeader/<name>,vpc-lattice-svcs:SourceVpc,vpc-lattice-svcs:SourceVpcOwnerAccount,vpc-lattice-svcs:ServiceNetworkArn, andvpc-lattice-svcs:ServiceArn.
AWS_IAM. Callers must sign requests with Sigv4 over vpc-lattice-svcs (the AWS SDK signs automatically when using the standard HTTP client with credentials in scope).4. VPC Lattice vs Alternatives
The table below is the most common decision matrix. Every row collapses one design dimension that teams compare across the four AWS-native options for east-west service-to-service connectivity.* You can sort the table by clicking on the column name.
| Property | VPC Lattice | PrivateLink (Endpoint Service) | Transit Gateway | ECS Service Connect / App Mesh |
|---|---|---|---|---|
| GA | March 2023 (core); December 2024 (Resource Configuration / Resource Gateway) | 2017 | November 2018 | Service Connect: November 2022. App Mesh: deprecation announced for 2026-09-30 |
| Layer | L4 (TLS passthrough) and L7 (HTTP/1.1 on HTTP listeners; HTTP/1.1, HTTP/2, gRPC on HTTPS listeners) | L4 (TCP / UDP transport via NLB) | L3 (IP routing) | L7 (HTTP / gRPC, Envoy-based) |
| Provider-side load balancer | Not required | NLB or GWLB required | N / A | Required if exposing externally |
| Cross-VPC, same Region | Native | Native | Native | Service Connect: within ECS cluster only |
| Cross-Account | Native (RAM) | Native (principal allow-list) | Native (RAM) | Service Connect: not native; App Mesh: via shared mesh |
| Cross-Region | No (per-Region Service Network) | Yes (cross-Region Endpoint Services since November 2024; cross-Region access to AWS services since November 2025) | Yes (peering) | No |
| CIDR overlap tolerated | Yes | Yes | No (must not overlap) | N / A |
| L7 routing (path / header) | Yes | No (NLB is L4) | No | Yes |
| Authorization model | IAM (Sigv4 signed requests + Auth Policy) | Endpoint principal allow-list + endpoint policy | None (network ACL + SG) | mTLS + Envoy filters |
| Per-request observability | Access logs (CW / S3 / Firehose) | VPC Flow Logs only | VPC Flow Logs only | Envoy access logs |
| Target types supported | Instance, IP, Lambda, ALB; Resource Configuration: RDS / IP / domain | Anything behind NLB or GWLB | All IP-reachable workloads | ECS / EKS containers |
| Best fit | New service-to-service deployments needing IAM and L7 routing across VPCs / accounts | Exposing a single service to a known set of consumer accounts | Bulk L3 connectivity, legacy systems, internet egress aggregation | In-cluster microservice traffic |
- CIDR overlap: Lattice and PrivateLink hide the provider's CIDR behind a managed endpoint. TGW exposes it. This single dimension is often the deciding factor between Lattice and TGW for federated business units.
- L7 routing: only Lattice and a sidecar mesh terminate HTTP at the data plane. Path-based canaries are a Lattice native; in PrivateLink they require an ALB behind the NLB.
- Cross-Region: Lattice does not span Regions. Multi-Region service-to-service architectures use one Service Network per Region and rely on Route 53 latency-based or weighted routing on top of the Lattice service DNS names.
5. Listener and Routing
The Listener-and-Rule layer is where Lattice differentiates from PrivateLink. This section walks through it in depth.5.1 Protocol selection
- HTTP — clear-text on port 80 (or any port you choose). Useful for legacy backends that cannot terminate TLS on their own and for the target side when the listener is TLS-terminating (Lattice terminates client TLS and forwards in cleartext to the target).
- HTTPS — TLS-terminated by the Lattice data plane on port 443 (or any). Requires a custom domain + ACM cert if you want a stable name; otherwise clients use the Lattice-generated DNS name with a wildcard cert that matches
*.vpc-lattice-svcs.<region>.on.aws. - TLS_PASSTHROUGH — Lattice does not terminate; the data plane copies bytes. Required when the target needs to see the client certificate (mTLS), or when the protocol on top is non-HTTP.
5.2 Rule ordering and match semantics
Rules are evaluated in priority order (lower number first). The first matching rule wins; no fallthrough. The default rule has prioritydefault and is the catch-all.A common idiom is a three-rule cascade:
- Priority 10:
Path = /admin/*→admin-tg(IAM allow-list restricted to operator role). - Priority 20:
Method = POST AND Path = /webhooks/*→webhook-tg(Lambda Target Group). - Default: forward to
app-tg(Instance Target Group fronting ECS tasks).
5.3 Weighted forwarding (canary)
A Rule'sforward action can split traffic by weight across multiple Target Groups. This is the native canary mechanism:
{
"action": {
"forward": {
"targetGroups": [
{ "targetGroupIdentifier": "tg-prod", "weight": 95 },
{ "targetGroupIdentifier": "tg-canary", "weight": 5 }
]
}
}
}
Sticky sessions are not supported at the rule level; canary splits are stateless on each request. For sticky-by-cookie deployments, fall back to an ALB target.5.4 Custom domain names
A Service can carry one custom domain name (api.example.internal) with one ACM certificate. The DNS record (typically a CNAME to the Lattice-generated DNS name) lives in a Route 53 Private Hosted Zone that is associated with the consumer VPC, or in a public zone if the Service Network has an internet-facing entry point (uncommon; Lattice is east-west).The certificate must be in the same Region as the Service and must be issued or imported into ACM (private CA-issued certs work via AWS Private CA, the service formerly named ACM Private CA / ACM PCA).
6. Auth Patterns
The auth surface is where Lattice replaces the principal allow-list of PrivateLink with full IAM policy. Three distinct patterns cover most production deployments.6.1 NONE — open service inside a trusted network
When the Service hasAuthType = NONE, the Service Network's auth policy (if any) still applies, but the Service itself accepts anonymous traffic. This is the right mode for:- Internal-only services in a single team's account, where the network boundary is the trust boundary.
- Cases where the application itself enforces authorization (the app already has its own JWT, mTLS, or API key validation).
6.2 AWS_IAM at the Service — per-service authorization
The Service's Auth Policy is a JSON resource policy. The simplest "allow this account" looks like:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccountB",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::222222222222:root"},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*"
}
]
}
A tighter version constrains the path and method:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OnlyOrdersReadFromOrgPrincipals",
"Effect": "Allow",
"Principal": "*",
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalOrgID": "o-abc123",
"vpc-lattice-svcs:RequestMethod": "GET"
},
"StringLike": {
"vpc-lattice-svcs:RequestPath": "/orders/*"
}
}
}
]
}
The IAM-identity-based policy on the caller side must independently grant vpc-lattice-svcs:Invoke on the Service ARN. Both sides must allow — IAM evaluation is identity-policy AND resource-policy.6.3 AWS_IAM at the Service Network — org-wide perimeter
Attaching an Auth Policy to the Service Network gives a single chokepoint for every Service in that network. A common pattern is:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyOutsideOrg",
"Effect": "Deny",
"Principal": "*",
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringNotEqualsIfExists": {
"aws:PrincipalOrgID": "o-abc123"
}
}
}
]
}
This effectively scopes every Service in the network to "callers from inside the AWS Organization." Individual Services can layer narrower allows on top.6.4 Sigv4 signing in the caller
Callers must Sigv4-sign requests with thevpc-lattice-svcs service identifier. The AWS SDK does this automatically when using a Lattice-aware HTTP client. With a plain HTTPS client (curl, requests, fetch), the signing must be done manually — most production setups inject signing as middleware (boto3 EventSystem, AWS Common Runtime Sigv4, or a Lambda Powertools helper).Lambda Target Groups receive an SDK-formatted event that includes the original signed request headers, the resolved IAM principal, and the matched path — applications can re-authorize at the function level by inspecting
requestContext.identity.7. Resource Configuration and Resource Gateway
Resource Configurations (and the Resource Gateways that front them) are the December-2024 additions that let VPC Lattice expose non-Service resources — an RDS instance, an arbitrary private IP, an on-premises host — to consumer VPCs and accounts. They are also what makes the new Resource VPC Endpoint (covered in the PrivateLink guide §5) work.7.1 What a Resource Configuration is
A Resource Configuration is a Lattice-managed object that describes a single resource by one of three types:- ARN type — an Amazon RDS DB instance or cluster, referenced by its ARN. Lattice resolves the DB's writer / reader endpoints automatically.
- IP type — a single IPv4 or IPv6 address and port. Useful for on-premises databases reached via Direct Connect.
- Domain Name type — a DNS name and port; Lattice resolves it inside the Resource VPC and forwards.
Each Resource Configuration is attached to a Resource Gateway in the resource's own VPC. The Resource Gateway is a Lattice-managed ENI per AZ in that VPC.
7.2 What a Resource Gateway is
A Resource Gateway is the provider-side foothold that Lattice creates in the VPC where the resource actually runs. It is an ENI per AZ, plus a Lattice control-plane registration. Once the gateway exists, multiple Resource Configurations can reuse it (one gateway can front many RDS instances or IP targets in the same VPC).7.3 Sharing a Resource Configuration
Resource Configurations are shareable through AWS RAM. The provider account creates the Configuration and shares it with consumer accounts. Each consumer account then creates a Resource VPC Endpoint (a new endpoint family, distinct from Interface endpoints) in its consumer VPC; the endpoint becomes the consumer-side ENI through which application traffic flows to the resource.The data path: Consumer EC2 → Resource VPC Endpoint ENI (consumer VPC) → AWS backbone → Resource Gateway ENI (provider VPC) → resource. No NLB, no public IP, no cross-account routing.
7.4 Resource vs Service — when each fits
- Service = an HTTP / gRPC / TLS endpoint that you control. Routing, auth policy, and observability are all Lattice features.
- Resource Configuration = a "raw" resource (DB, IP, domain) that you cannot wrap in a Service. Auth is via the consumer's IAM (calls go through the Resource VPC Endpoint, which carries an endpoint policy), not via a Lattice Auth Policy.
8. Architecture Patterns
This section walks through the production patterns most teams converge on.8.1 Hub-and-Spoke Service Network
A single Service Network in a central "shared services" account is associated with consumer VPCs across spoke accounts via AWS RAM. Services owned by domain accounts (orders, billing, inventory) associate themselves with the central network. Every consumer VPC sees every Service through one DNS surface.Advantages:
- Single point for network-wide Auth Policy (e.g., "deny callers outside the org").
- Single access-log subscription captures all east-west traffic.
- Service owners do not need to coordinate with consumers; the central network handles association.
- The shared services account becomes a control plane to be governed carefully — SCPs and IAM controls on
vpc-lattice:CreateServiceNetwork*andvpc-lattice:AssociateServiceshould be tight. - Blast radius of a misconfigured network policy is org-wide.
8.2 Per-Environment Service Networks
Three networks (prod, staging, dev), one per environment. Services exist once but associate with the appropriate network. Auth Policies on each network enforce environment isolation (e.g., the prod policy denies any caller from a dev account).Advantages:
- Hard isolation by environment.
- Same Service ARN visible in multiple networks; consumers in each environment resolve to the right endpoint via the network-specific DNS name.
- Operating three networks doubles or triples the number of associations to manage.
- Cross-environment debugging (call from staging to prod) is intentionally hard; treat as a feature.
8.3 Multi-Account "Hub of Hubs" with Resource Gateways for Data
Service Network in the platform account associates with VPCs in business-unit accounts. Each business-unit account also exposes its own database resources via Resource Configuration, registered through Resource Gateways in the BU's own VPC and shared via RAM to the platform account. The platform account in turn re-shares to consumer VPCs.Advantages:
- Each BU keeps its data plane (RDS, on-prem) in its own account.
- The platform account is a thin policy layer, not a data path.
- Two layers of RAM shares per resource (BU → platform, platform → consumer) require disciplined automation.
8.4 Cross-Region (and why Lattice does not span)
A Service Network is regional. Multi-Region service deployments use one Service Network per Region. The recommended pattern is one of:- Active-active: deploy the same Service in two Regions, register both DNS names in a Route 53 latency-based routing policy, and let the resolver pick the lowest-latency Region per consumer.
- Active-passive: register both DNS names with a primary / secondary failover policy and a Route 53 health check against the active Region's Lattice DNS name.
us-east-1 can only associate with a Service Network in us-east-1.9. Implementation Walkthrough — Console, CDK, and Terraform
End-to-end deployment in three forms: Console, CDK (TypeScript), and Terraform. All three deploy the same minimal topology: a Service Network, one Service with an HTTPS listener forwarding to a Lambda Target Group, and a consumer VPC association.9.1 Console — the click path
- Create a Service Network: VPC console → VPC Lattice → Service networks → Create service network. Name, optional Auth Type (
NONEfor first deploy; switch toAWS_IAMonce policies are drafted), optional access log subscription. - Create a Service: Services → Create service. Name, optional custom domain, optional ACM certificate. Set Auth Type and (if
AWS_IAM) the Auth Policy. - Attach a Listener: in the Service, Add listener → HTTPS:443, default action Forward to target group.
- Create a Target Group: Target groups → Create. Type Lambda → select the function ARN.
- Associate Service with Service Network: in the Service Network, Associate services → pick the new Service.
- Associate consumer VPC: in the Service Network, VPC associations → pick the consumer VPC.
- Update consumer security groups: the VPC association creates Lattice ENIs that egress to the consumer's instances. The consumer instance's SG needs to allow inbound from the Lattice managed prefix list (the console surfaces it during association).
https://<service-name>-<service-id>.<service-network-id>.vpc-lattice-svcs.<region>.on.aws/ (or to the custom domain CNAME).9.2 CDK (TypeScript) — infrastructure as code
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lattice from 'aws-cdk-lib/aws-vpclattice';
import { Construct } from 'constructs';
export class LatticeStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const consumerVpc = ec2.Vpc.fromLookup(this, 'ConsumerVpc', { vpcId: 'vpc-0consumer' });
const fn = new lambda.Function(this, 'OrdersFn', {
runtime: lambda.Runtime.PYTHON_3_12,
handler: 'index.handler',
code: lambda.Code.fromInline(
'def handler(event, ctx):\n return {"statusCode": 200, "body": "ok"}'
),
});
const sn = new lattice.CfnServiceNetwork(this, 'Sn', {
name: 'shared',
authType: 'AWS_IAM',
});
const svc = new lattice.CfnService(this, 'Svc', {
name: 'orders',
authType: 'AWS_IAM',
});
const tg = new lattice.CfnTargetGroup(this, 'Tg', {
type: 'LAMBDA',
name: 'orders-tg',
targets: [{ id: fn.functionArn }],
});
const listener = new lattice.CfnListener(this, 'L', {
serviceIdentifier: svc.attrId,
name: 'https',
protocol: 'HTTPS',
port: 443,
defaultAction: {
forward: {
targetGroups: [{ targetGroupIdentifier: tg.attrId, weight: 100 }],
},
},
});
listener.addDependency(tg);
new lattice.CfnServiceNetworkServiceAssociation(this, 'SnSvc', {
serviceNetworkIdentifier: sn.attrId,
serviceIdentifier: svc.attrId,
});
new lattice.CfnServiceNetworkVpcAssociation(this, 'SnVpc', {
serviceNetworkIdentifier: sn.attrId,
vpcIdentifier: consumerVpc.vpcId,
});
}
}
The L1 (Cfn*) constructs are the canonical way to author VPC Lattice in CDK as of early 2026; higher-level L2 abstractions are still evolving.9.3 Terraform — same deployment
resource "aws_vpclattice_service_network" "sn" {
name = "shared"
auth_type = "AWS_IAM"
}
resource "aws_vpclattice_service" "svc" {
name = "orders"
auth_type = "AWS_IAM"
}
resource "aws_vpclattice_target_group" "tg" {
name = "orders-tg"
type = "LAMBDA"
targets {
id = aws_lambda_function.orders.arn
}
}
resource "aws_vpclattice_listener" "l" {
name = "https"
protocol = "HTTPS"
port = 443
service_identifier = aws_vpclattice_service.svc.id
default_action {
forward {
target_groups {
target_group_identifier = aws_vpclattice_target_group.tg.id
weight = 100
}
}
}
}
resource "aws_vpclattice_service_network_service_association" "sn_svc" {
service_identifier = aws_vpclattice_service.svc.id
service_network_identifier = aws_vpclattice_service_network.sn.id
}
resource "aws_vpclattice_service_network_vpc_association" "sn_vpc" {
vpc_identifier = data.aws_vpc.consumer.id
service_network_identifier = aws_vpclattice_service_network.sn.id
}
Both stacks above intentionally omit Auth Policy resources (aws_vpclattice_auth_policy in Terraform, CfnAuthPolicy in CDK) — start with NONE to validate the wiring, then switch to AWS_IAM and add policy in a second deploy.10. Observability
Lattice ships three observability surfaces. Use all three; they answer different questions.10.1 Access logs
Per-request, JSON-formatted, one record per HTTP request or TLS connection. Configurable destination: CloudWatch Logs, S3, or Kinesis Data Firehose. Record fields includesourceVpcId, principal (the resolved IAM identity), requestMethod, requestPath, responseCode, bytesReceived, bytesSent, serviceArn, targetGroupArn, requestId, and connection-level TLS metadata. Access logs are the only way to attribute per-request behavior to a specific caller and target group.A common pattern for cost: route access logs to S3 + Athena rather than CloudWatch Logs Insights; access-log volume on a busy Service can dwarf application-log volume and Athena's per-scan billing is more forgiving than CloudWatch Logs Insights for retrospective queries.
10.2 CloudWatch metrics
Lattice publishes metrics under theAWS/VpcLattice namespace. The most commonly used:| Metric | Dimensions | Use |
|---|---|---|
| TotalRequestCount | Service / TargetGroup / ServiceNetwork | Throughput |
| HTTPCode_Target_2XX_Count | Service / TargetGroup | Success rate |
| HTTPCode_Target_4XX_Count | Service / TargetGroup | Caller errors |
| HTTPCode_Target_5XX_Count | Service / TargetGroup | Target errors |
| RequestTime | Service / TargetGroup | End-to-end latency |
| TargetTLSNegotiationErrorCount | TargetGroup | TLS handshake failures |
| HealthyHostCount | TargetGroup | Healthy target count |
| UnHealthyHostCount | TargetGroup | Unhealthy target count |
| NewConnectionCount | Service | Connection establishment rate |
| ActiveConnectionCount | Service | Concurrency snapshot |
RequestTime > 1 s over 10 minutes, UnHealthyHostCount > 0 for 2 minutes.10.3 VPC Flow Logs on the Lattice ENIs
The Lattice ENIs in consumer VPCs emit VPC Flow Logs like any other ENI. Flow logs are useful for connection-level visibility (was anything attempted from this caller IP at all?) but cannot see inside TLS-terminated traffic — for that, use access logs.10.4 Service map (in AWS console)
The VPC Lattice console exposes a Service map view that derives a directed graph of Service → Service calls from access logs. Useful for onboarding and for catching unexpected callers. Not a substitute for proper service-mesh observability (X-Ray, ADOT, OpenTelemetry collectors) on the application side.11. Use Cases
Three reference deployments distill the high-leverage uses.11.1 Microservice-to-microservice (single team, single account)
Service Networkteam-a, all team-A microservices register as Services and associate with the network. Consumer VPCs (one per stage, dev / staging / prod) associate. Auth Policy on the network requires aws:PrincipalOrgID == o-abc123, ruling out non-org callers. Each Service further requires the calling principal's role to be inside a team-A IAM path (/team-a/*).The team gets: cross-VPC reachability without TGW, IAM-based service authorization, access-logs free of charge, and no NLB.
11.2 Multi-account "platform" hosting
Platform account owns a shared Service Network. Domain accounts (orders, billing, identity) each own their Services and share them into the platform Service Network via Lattice's service-association RAM share. Consumer applications in product accounts associate their VPCs with the platform Service Network. Result: one DNS surface per Service, one Auth Policy chokepoint, every team retains autonomy over their own service code and Lambda targets.11.3 SaaS multi-tenant data plane
A SaaS provider runs the workload in its own AWS account. Each enterprise customer brings their own AWS account and consumer VPC. The provider creates a Service Network and shares it via RAM to each customer; customers associate their VPC with the network and call the provider's Service from inside their own VPC. Auth Policy on the Service identifies the calling principal byaws:PrincipalAccount and the Service's per-tenant logic uses the matched principal to scope the response (multi-tenant isolation at L7).The advantages over PrivateLink Endpoint Service for the same use case: no NLB on the provider side, IAM-rich authorization rather than principal allow-list, per-tenant access logs out of the box, and L7 routing (the same Service can expose different paths to different tenant tiers).
12. Common Pitfalls — A Field Checklist
A checklist of issues observed often enough to be worth listing explicitly. Run through it before declaring a Lattice deployment "done."- Forgetting the consumer security group. Lattice ENIs in the consumer VPC originate traffic to the consumer's instances. The instance's SG must allow inbound from the Lattice managed prefix list, not from the caller's IP.
- Auth Policy logic inverted (identity vs resource policy). When the Service is
AWS_IAM, the caller's IAM identity policy must independently allowvpc-lattice-svcs:Invokeon the Service ARN. A Service Auth Policy that allows the principal is insufficient; both sides must allow. - Sigv4 signing missing on the caller. Calling an
AWS_IAMService with a plaincurlreturns403 AccessDeniedException. The caller must Sigv4-sign withvpc-lattice-svcsas the service. - Wildcard CN on Lattice-generated DNS. The auto-generated DNS name is covered by a Lattice-managed wildcard ACM certificate (
*.vpc-lattice-svcs.<region>.on.aws). A client that pins the cert (TLS certificate pinning) breaks on rotation. Use a custom domain + your own ACM cert if pinning is required. - Custom domain DNS not resolving in consumer VPC. The custom domain must be in a Route 53 Private Hosted Zone that is associated with the consumer VPC, not just with the provider VPC. Multi-account setups also need cross-account PHZ association.
- Lambda Target Group event format mismatch. The event Lattice delivers to Lambda is NOT API Gateway proxy format. Functions ported from API Gateway need a small shim to map
requestContext.httpandbodyfields. - Lattice link-local range conflict (rare). The Lattice ENI range is link-local and reserved; some VPCs have static routes overlapping the broader
169.254.0.0/16block (e.g., for IMDS). Lattice's specific subrange (169.254.171.0/24for IPv4 andfd00:ec2:80::/64for IPv6) is dedicated, but custom on-prem return routes that match the broader link-local range can confuse troubleshooting. - Service Network deletion blocked by associations. A Service Network with active VPC or Service associations cannot be deleted. Disassociate all VPCs and Services first; the console does not always surface the blocker clearly.
- Cross-account share accepted but VPC still cannot resolve. The RAM share invitation must be accepted and the consumer must explicitly associate its VPC with the shared Service Network. Acceptance alone does not auto-associate.
- Mixing
TLS_PASSTHROUGHand HTTPS on one Service. Not allowed; a Service is either an HTTP-family Service (HTTP and / or HTTPS listeners) or a TLS-passthrough Service, not both. - Auth Policy condition keys typed wrong.
vpc-lattice-svcs:RequestPathis a string condition (useStringLike,StringEquals), not an ARN condition. Confusingaws:PrincipalArn(which is anArnEquals/ArnLikecondition) withPrincipal(the top-level field) breaks evaluation silently. - No access logs configured by default. A newly created Service has no logging. Forgetting to attach an access-log subscription means an entire production deployment with no per-request visibility.
- Mixing Service Network Auth Policies and Service Auth Policies without testing both. The two policies AND together. A "Deny outside org" at the network is correctly restrictive even if the Service's policy says "Allow anyone."
- Resource Gateway placed in only one AZ. The Resource Gateway should span the resource VPC's AZs that hold the resource. A single-AZ gateway loses access to RDS reader endpoints in the other AZs.
13. Frequently Asked Questions
Q: Can I use VPC Lattice and AWS PrivateLink together?Yes. PrivateLink (Interface or Resource endpoint) and Lattice are independent. Many teams expose third-party SaaS via PrivateLink (where the provider requires it) and internal services via Lattice (where the team controls both ends).
Q: Does VPC Lattice support gRPC?
Yes, on HTTPS listeners only. VPC Lattice negotiates HTTP/2 via ALPN on HTTPS listeners (HTTP listeners are HTTP/1.1 only), and gRPC bodies pass through transparently. The Lattice access log records gRPC status codes alongside HTTP statuses.
Q: Is there a free tier?
No standalone free tier specifically for Lattice. Pricing is per-Service-hour (services with at least one association are billable), per-request, and per-GB processed. Refer to the AWS VPC Lattice pricing page for current numbers.
Q: Can I share a Service Network across AWS Organizations?
Not directly; AWS RAM supports sharing within an Organization or to an explicit list of accounts. Cross-Organization sharing is via account-by-account RAM invitations.
Q: Can the Lattice data plane terminate mTLS?
No. Lattice terminates server-side TLS only. For mTLS, use a
TLS_PASSTHROUGH listener and let the target handle the client certificate.Q: How does Lattice handle CIDR overlap?
The Lattice control plane assigns each consumer VPC a Lattice-managed link-local ENI. The caller's local VPC CIDR is irrelevant to whether the call reaches the target; Lattice does not require non-overlapping CIDRs the way TGW does.
Q: What is the maximum number of Services I can associate with a Service Network?
The current service quota is published in the VPC Lattice quotas documentation. Adjust expectations by checking the live quota rather than memorizing a number that will change.
Q: Does Lattice replace AWS App Mesh?
For the in-cluster Envoy-mesh use case, no — Lattice has no sidecar. For the broader "service-to-service across VPCs and accounts with managed routing and authorization" use case, yes. AWS announced App Mesh deprecation effective 2026-09-30; new mesh-style deployments should target Lattice (for cross-cluster) and ECS Service Connect or self-managed Istio (for in-cluster).
Q: Can a Service be associated with multiple Service Networks?
Yes. Each association is independent and can have a different auth policy at the network layer.
Q: How does failover between Lattice and a non-Lattice fallback work?
Lattice exposes a stable DNS name. Failover is handled at the DNS layer (Route 53 health checks against the Lattice DNS) or at the application layer (try-Lattice-then-fallback). There is no built-in active-passive mode within Lattice itself.
Q: Can Lattice expose a service to the public internet?
Not directly. Lattice is east-west. Internet-facing services should sit behind CloudFront, API Gateway, or an internet-facing ALB; those edges can then call Lattice as their backend if needed.
14. Summary
VPC Lattice collapses a stack of moving parts — TGW + SGs for network reach, NLB + PrivateLink for service exposure, App Mesh / Service Connect for L7 routing, custom IAM authorization for service-to-service auth — into one managed control plane. Its strengths are:- No CIDR coordination — link-local ENIs in each consumer VPC sidestep the overlap problem.
- IAM as the authorization model — Auth Policies, identity policies, and SCPs all describe service-to-service calls in the language teams already use for AWS service calls.
- L7 routing at the data plane — path-based dispatch and weighted canary without a self-managed sidecar.
- Cross-account by AWS RAM — a Service Network shared into consumer accounts is one of the cleanest multi-account patterns AWS has shipped.
- Resource Configurations — the December-2024 additions extend Lattice from "your services" to "your private resources" (RDS, IP, domain), and they are the underlying mechanism for the new Resource VPC Endpoints covered in the PrivateLink guide.
The internal companion pieces — the per-endpoint deep dive in AWS PrivateLink and VPC Endpoints Complete Guide - Interface, Gateway, and Resource Endpoint, the CIDR-and-routing layer in VPC Design Review Checklist - CIDR, Subnets, Transit Gateway, and the terminology reference in AWS Networking Glossary — together cover the surrounding architecture context.
15. References
- What is Amazon VPC Lattice?
- VPC Lattice concepts
- Service Network associations
- Auth policies for VPC Lattice
- Resource configurations
- Resource gateways
- VPC Lattice quotas
- AWS VPC Lattice pricing
- VPC Lattice access logs
- VPC Lattice CloudWatch metrics
- Lambda targets for VPC Lattice
- Sharing VPC Lattice resources via AWS RAM
- Migrating from AWS App Mesh to Amazon ECS Service Connect
- AWS PrivateLink and VPC Endpoints Complete Guide - Interface, Gateway, and Resource Endpoint
- VPC Design Review Checklist - CIDR, Subnets, Transit Gateway
- AWS Networking Glossary
- AWS History and Timeline - Overview of AWS Services and Their Releases
References:
Tech Blog with curated related content
Written by Hidekazu Konishi