Skip to content

AWSVPCLattice

Dennis Lee edited this page Jul 11, 2026 · 1 revision

title: AWS VPC Lattice type: platform created: 2026-07-11 last_updated: 2026-07-11 related: ["radar/techniques/AWSSaaSLens", "radar/techniques/CloudFormationIaCGenerator"] sources: ["https://aws.amazon.com/vpc/lattice/", "https://aws.amazon.com/blogs/aws/introducing-vpc-lattice-simplify-networking-for-service-to-service-communication-preview/", "https://aws.amazon.com/blogs/aws/simplify-service-to-service-connectivity-security-and-monitoring-with-amazon-vpc-lattice-now-generally-available/", "https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-vpc-vattice-modernize-and-simplify-your-enterprise-network-architectures/", "https://aws.amazon.com/blogs/networking-and-content-delivery/build-secure-multi-account-multi-vpc-connectivity-for-your-applications-with-amazon-vpc-lattice/", "https://aws.amazon.com/blogs/networking-and-content-delivery/use-amazon-vpc-lattice-to-streamline-and-secure-tcp-resource-connectivity-across-multiple-aws-accounts/", "https://aws.amazon.com/blogs/networking-and-content-delivery/securing-service-communications-combining-vpc-lattice-with-network-firewall/", "https://registry.terraform.io/providers/hashicorp/aws/latest/docs"] radar_quadrant: Platforms radar_ring: Assess radar_position: inner

AWS VPC Lattice

AWS VPC Lattice is a fully managed application-networking service that connects, secures, and monitors service-to-service communication across VPCs and AWS accounts without requiring VPC peering, route table management, or manual handling of overlapping IP ranges. It operates at the application layer, supporting HTTP, HTTPS, gRPC, and TCP workloads.

Architecture

The core object model, introduced at preview and extended through general availability, consists of four pieces. A service network is the logical boundary that automates service discovery and connectivity, and applies access and observability policy across a collection of services. A service is an independently deployable unit that can span multiple VPCs and accounts, backed by any mix of EC2 instances, containers, or serverless compute. A target group is the set of compute resources, EC2, Lambda, or Kubernetes pods via the AWS Gateway API Controller, handling a given workload. A listener defines the port and protocol and holds prioritized routing rules with a default catch-all rule.

At general availability, AWS added custom domains with SSL/TLS, Kubernetes-native support, Application and Network Load Balancers as valid targets, and IPv6 support, per the GA announcement. A later addition, the resource gateway and resource configuration pair, extends Lattice beyond compute to non-compute TCP resources: a resource configuration can reference an RDS database by ARN, letting clients in consumer VPCs reach it through its private DNS endpoint across account boundaries.

The most concrete architectural differentiator appears in AWS's multi-account, multi-VPC walkthrough: traffic between services routes through reserved link-local address space (169.254.0.0/16 and fc00::/7), which sidesteps the overlapping-CIDR conflicts that make VPC peering unworkable once an organization has enough accounts. The pattern also separates concerns cleanly: network administrators own the service network, while individual service owners manage their own services and IAM-based access policies.

How Link-Local Addressing Works at Layer 3

DNS resolution is the mechanism, not manual routing. When a client resolves a Lattice service's DNS name, the Route53 VPC Resolver returns a link-local address, from 169.254.0.0/16 for IPv4 or fc00::/7 for IPv6, rather than an address inside the target service's real VPC CIDR, per AWS's own walkthrough. VPC Lattice maintains a managed prefix list per account, and route tables of VPCs associated with the service network are automatically updated with these link-local addresses, so no manual peering or route configuration between the client and target VPCs is required. The client's packet is addressed to the link-local IP (for example 169.254.171.23), routed by the subnet route table to VPC Lattice's own managed infrastructure, which then forwards it to the real target. Because the client's routing decision never depends on the target VPC's actual address space, two VPCs with identical overlapping CIDRs (both using 10.0.0.0/16, for instance) can still connect through Lattice without conflict.

Access Control at Layer 7: the PARC Model

VPC Lattice enforces authorization using the same IAM-based model AWS calls PARC, principal, action, resource, and condition, applied to service-to-service calls rather than AWS API calls, per the preview announcement. Access policies attach at two points: the service network, for a broad default, and individual services, for narrower per-service overrides, the same layering relationship as organization SCPs versus IAM policies. A policy statement can restrict which principal (an IAM role or account) may call which resource (a specific service), under which condition (standard IAM condition keys such as source VPC or tags). This authorization layer is distinct from listener routing rules, which decide where a request goes based on path (AWS's example routes /to-instance and /to-function to different target groups); PARC policies decide whether the request is allowed at all, so the two compose independently. Every request is signed with SigV4, the same request-signing scheme used for AWS API calls, letting Lattice verify caller identity cryptographically per request rather than per network connection.

Positioning vs Other AWS Networking

AWS does not, in any of its own VPC Lattice content, position the service head-to-head against App Mesh or API Gateway. Instead it describes Lattice as built on existing primitives rather than a replacement for them. The modernization post states that Lattice's service-network VPC endpoints are powered by AWS PrivateLink, and that Transit Gateway and Cloud WAN remain the path for cross-Region connectivity, with Direct Connect and Site-to-Site VPN handling hybrid connectivity alongside Lattice rather than being displaced by it. The Network Firewall integration post draws the clearest boundary: Lattice provides identity-based, layer-7 authorization (SigV4 signing, IAM policy) for routine service-to-service traffic, while Network Firewall retains responsibility for deep packet inspection and threat detection on sensitive workloads, such as database traffic carrying sensitive data, through a centralized Transit-Gateway-based inspection pattern. AWS is explicit that Lattice does not replace Network Firewall, it offloads non-inspection traffic from it.

IaC and Terraform

None of AWS's six official VPC Lattice blog posts mention Terraform. The preview and GA announcements walk through the AWS Console exclusively; the TCP resource connectivity post uses AWS CLI commands; the multi-account post is the only one to reference an IaC tool at all, pointing to CloudFormation templates hosted in a linked GitHub repository rather than inlining code. AWS's own guidance treats CloudFormation as the default IaC path for Lattice and does not acknowledge Terraform anywhere in its content.

Independently, the hashicorp/aws Terraform provider carries full, actively maintained VPC Lattice coverage: fifteen resources spanning vpclattice_service_network, vpclattice_service, vpclattice_listener, vpclattice_listener_rule, vpclattice_target_group and vpclattice_target_group_attachment, all three association types (VPC, service, resource), vpclattice_auth_policy and vpclattice_resource_policy, vpclattice_resource_gateway, vpclattice_resource_configuration, vpclattice_domain_verification, and vpclattice_access_log_subscription. The provider was at v6.54.0 as of 2026-07-08, and the resource_gateway resource, one of Lattice's newer features, was last updated 2026-06-08, confirming the provider tracks new Lattice functionality closely despite AWS's silence on Terraform in its own materials.

CloudFormation Reference

AWS's own blog content never shows CloudFormation code inline (see IaC and Terraform, above), so this section fills that gap directly against the CloudFormation resource reference for AWS::VpcLattice::* types.

Minimal Service Network, Service, Target Group, and Listener

A bare service network, service, and one VPC association, with a target group and listener wired to accept HTTP traffic on port 80. There is no separate TargetGroupAttachment CloudFormation resource, that exists only in the Terraform provider, targets attach inline via the Targets property on AWS::VpcLattice::TargetGroup itself.

AWSTemplateFormatVersion: "2010-09-09"
Description: Minimal AWS VPC Lattice setup with one listener and one target group

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
  TargetIp:
    Type: String
    Description: IP address of the target (target group type IP)

Resources:
  ServiceNetwork:
    Type: AWS::VpcLattice::ServiceNetwork
    Properties:
      Name: my-service-network
      AuthType: NONE

  Service:
    Type: AWS::VpcLattice::Service
    Properties:
      Name: my-service
      AuthType: NONE

  ServiceNetworkVpcAssociation:
    Type: AWS::VpcLattice::ServiceNetworkVpcAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetwork
      VpcIdentifier: !Ref VpcId

  ServiceNetworkServiceAssociation:
    Type: AWS::VpcLattice::ServiceNetworkServiceAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetwork
      ServiceIdentifier: !Ref Service

  TargetGroup:
    Type: AWS::VpcLattice::TargetGroup
    Properties:
      Name: my-target-group
      Type: IP
      Config:
        Port: 80
        Protocol: HTTP
        VpcIdentifier: !Ref VpcId
      Targets:
        - Id: !Ref TargetIp
          Port: 80

  Listener:
    Type: AWS::VpcLattice::Listener
    Properties:
      Name: my-listener
      ServiceIdentifier: !Ref Service
      Protocol: HTTP
      Port: 80
      DefaultAction:
        Forward:
          TargetGroups:
            - TargetGroupIdentifier: !Ref TargetGroup

Target group type is one of IP | LAMBDA | INSTANCE | ALB, per the TargetGroup reference; LAMBDA and ALB types skip most of Config (health check, port, protocol, VPC ID are not supported or behave differently for those types).

Cross-VPC Pattern with IAM Auth and an ALB Target

A two-stack pattern for the case where the calling application and the target service sit in different VPCs, here named ace (the caller) and appcs (hosts the ALB being fronted by Lattice). Both the service network and the service carry AuthType: AWS_IAM, which per AWS's own auth-policies guide means all traffic is denied by default until an explicit auth policy allows it, at both layers.

Setting AuthType: AWS_IAM only on the service and leaving the service network at NONE is a real option, and narrows the blast radius of getting a single service's policy wrong, but it removes the network-level baseline entirely: any other service later added to the same network with no AuthType set defaults to open, since the network-level check is skipped when the network's own AuthType is NONE. Setting AWS_IAM at both layers means a request must clear two independent explicit-allow checks, per AWS's authorization evaluation logic, so a misconfigured or forgotten per-service policy does not silently leave that service world-reachable.

Stack 1 (appcs) — service network, service, ALB target, listener, and auth policies at both layers:

AWSTemplateFormatVersion: "2010-09-09"
Description: VPC Lattice service network, service, and ALB target in VPC appcs

Parameters:
  AppcsVpcId:
    Type: AWS::EC2::VPC::Id
  AceVpcId:
    Type: String
    Description: VPC ID of ace, the calling VPC, used in both auth policy conditions
  AlbArn:
    Type: String
    Description: ARN of the internal ALB in appcs
  AceAppRoleArn:
    Type: String
    Description: ARN of the IAM role assumed by the calling application in ace

Resources:
  ServiceNetwork:
    Type: AWS::VpcLattice::ServiceNetwork
    Properties:
      Name: my-service-network
      AuthType: AWS_IAM

  Service:
    Type: AWS::VpcLattice::Service
    Properties:
      Name: my-service
      AuthType: AWS_IAM
      Tags:
        - Key: Environment
          Value: prod

  AppcsVpcAssociation:
    Type: AWS::VpcLattice::ServiceNetworkVpcAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetwork
      VpcIdentifier: !Ref AppcsVpcId

  ServiceNetworkServiceAssociation:
    Type: AWS::VpcLattice::ServiceNetworkServiceAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetwork
      ServiceIdentifier: !Ref Service

  TargetGroup:
    Type: AWS::VpcLattice::TargetGroup
    Properties:
      Name: my-alb-target-group
      Type: ALB
      Config:
        Port: 80
        Protocol: HTTP
        VpcIdentifier: !Ref AppcsVpcId
      Targets:
        - Id: !Ref AlbArn
          Port: 80

  Listener:
    Type: AWS::VpcLattice::Listener
    Properties:
      Name: my-listener
      ServiceIdentifier: !Ref Service
      Protocol: HTTP
      Port: 80
      DefaultAction:
        Forward:
          TargetGroups:
            - TargetGroupIdentifier: !Ref TargetGroup

  ServiceNetworkAuthPolicy:
    Type: AWS::VpcLattice::AuthPolicy
    Properties:
      ResourceIdentifier: !Ref ServiceNetwork
      Policy:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: [!Ref AceAppRoleArn]
            Action: "vpc-lattice-svcs:Invoke"
            Resource: "*"
            Condition:
              StringEquals:
                vpc-lattice-svcs:SourceVpc: !Ref AceVpcId
                aws:ResourceTag/Environment: prod

  ServiceAuthPolicy:
    Type: AWS::VpcLattice::AuthPolicy
    Properties:
      ResourceIdentifier: !Ref Service
      Policy:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              AWS: [!Ref AceAppRoleArn]
            Action: "vpc-lattice-svcs:Invoke"
            Resource: !Sub "arn:aws:vpc-lattice:${AWS::Region}:${AWS::AccountId}:service/${Service}/api/*"
            Condition:
              StringEquals:
                vpc-lattice-svcs:SourceVpc: !Ref AceVpcId
                vpc-lattice-svcs:RequestMethod: GET

Outputs:
  ServiceNetworkArn:
    Value: !GetAtt ServiceNetwork.Arn
    Export:
      Name: my-service-network-arn

Stack 2 (ace) — associates the calling VPC to the shared service network:

AWSTemplateFormatVersion: "2010-09-09"
Description: Associate VPC ace with the shared VPC Lattice service network

Parameters:
  AceVpcId:
    Type: AWS::EC2::VPC::Id
  ServiceNetworkArn:
    Type: String
    Description: ARN of the service network from the appcs stack; pass explicitly for cross-account, since ServiceNetworkIdentifier must be an ARN, not a bare ID, when the resources are in different accounts

Resources:
  AceVpcAssociation:
    Type: AWS::VpcLattice::ServiceNetworkVpcAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetworkArn
      VpcIdentifier: !Ref AceVpcId

ServiceNetworkVpcAssociation is the only resource ace's stack needs, per AWS's own multi-account walkthrough this association "gets created in the service network account and the VPC owner account," so ace's stack is exactly the VPC-owner side of that association.

Auth Policy Layering: Network Baseline and Service Least Privilege

The two AuthPolicy resources above enforce different things and compose rather than duplicate:

The network-level policy is the baseline gate every service in the network must clear. Its Resource is "*" rather than one service's ARN, since hardcoding a single service ARN here would make the network-level policy redundant with the service-level one and would silently fail to cover any future service added to the network. Instead it scopes by the aws:ResourceTag/Environment: prod condition, so only tagged services get any grant from this policy at all; untagged or non-prod services are unreachable through it regardless of caller. Combined with vpc-lattice-svcs:SourceVpc, this is: any invocation of a prod-tagged service, from ace, by the named role.

The service-level policy narrows further, specific to this one service: Resource is scoped to a /api/* path rather than the whole service, and vpc-lattice-svcs:RequestMethod: GET blocks writes even if the role's identity policy is later broadened to allow more actions.

A looser, VPC-only variant of the service-level policy is also valid depending on threat model, trading identity and path specificity for simplicity: Principal: "*" plus Condition: { StringNotEquals: { aws:PrincipalType: Anonymous }, StringEquals: { vpc-lattice-svcs:SourceVpc: <ace-vpc-id> } }, any authenticated caller from ace, no identity or path restriction. This is the pattern AWS itself documents as "Example 3" in the auth-policies guide.

Hardening

Beyond the auth-policy layering above, AWS's security guide documents hardening across several other dimensions. Each extends the appcs-stack.yaml resources from the Cross-VPC Pattern section.

Security Groups on the VPC Association

A distinct control plane from PARC auth policies: this operates at layer 3/4 (which resources within the associated VPC can even reach the service network), while auth policies operate at layer 7 (which authenticated identity can invoke which path). Not attaching a security group here means every resource in that VPC can attempt to reach the service network, relying entirely on the auth policy to gate it.

  AceAppSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Restrict which resources in appcs can reach the service network
      VpcId: !Ref AppcsVpcId
      SecurityGroupEgress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  AppcsVpcAssociation:
    Type: AWS::VpcLattice::ServiceNetworkVpcAssociation
    Properties:
      ServiceNetworkIdentifier: !Ref ServiceNetwork
      VpcIdentifier: !Ref AppcsVpcId
      SecurityGroupIds:
        - !Ref AceAppSecurityGroup

ServiceNetworkVpcAssociation.SecurityGroupIds accepts up to 5 groups per association, per the ServiceNetworkVpcAssociation reference.

HTTPS Listener with TLS

VPC Lattice enforces TLS 1.2 minimum, TLS 1.3 recommended, per AWS's infrastructure security guidance, non-configurable, so there is no cipher-suite property to set. Swapping the listener's protocol and port and adding a certificate is the only change needed:

  Service:
    Type: AWS::VpcLattice::Service
    Properties:
      Name: my-service
      AuthType: AWS_IAM
      CertificateArn: !Ref AcmCertificateArn

  Listener:
    Type: AWS::VpcLattice::Listener
    Properties:
      Name: my-listener
      ServiceIdentifier: !Ref Service
      Protocol: HTTPS
      Port: 443
      DefaultAction:
        Forward:
          TargetGroups:
            - TargetGroupIdentifier: !Ref TargetGroup

A plain HTTP listener, as used in the earlier minimal templates, carries no transport encryption at all.

Encryption at Rest for Access Logs

  AccessLogBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256

Per AWS's data protection guidance, enabling SSE-S3 on the destination bucket causes each access log file to be encrypted automatically before storage. This is standard AWS::S3::Bucket syntax, not a VPC Lattice-specific property; the certificate's own private key encryption, via an AWS-managed KMS grant scoped to the service's ARN as encryption context, is automatic and has no CloudFormation-configurable property.

Access Logs (Disabled by Default)

Access logs are optional and off by default at both the service and service-network level, for both services and resource configurations, per AWS's access-log documentation. Without enabling them there is no record of individual requests.

  ServiceAccessLogs:
    Type: AWS::VpcLattice::AccessLogSubscription
    Properties:
      ResourceIdentifier: !Ref Service
      DestinationArn: !GetAtt AccessLogBucket.Arn

  ServiceNetworkAccessLogs:
    Type: AWS::VpcLattice::AccessLogSubscription
    Properties:
      ResourceIdentifier: !Ref ServiceNetwork
      DestinationArn: !GetAtt AccessLogBucket.Arn
      ServiceNetworkLogType: SERVICE

DestinationArn accepts a CloudWatch Log group, S3 bucket, or Firehose delivery stream ARN. ServiceNetworkLogType (SERVICE | RESOURCE) only applies at the network level, distinguishing service traffic logs from resource-configuration traffic logs. The log schema includes an authDeniedReason field (Service, Network, or Identity) that reveals exactly which policy layer rejected a given request, directly useful for validating that the network-level and service-level auth policies above are each doing real work rather than one layer silently absorbing all rejections.

Restricting Transitive Traffic to a PrivateLink-Backed VPC Endpoint

Client traffic arriving via VPC peering, Transit Gateway, Direct Connect, or VPN can only reach a service network through a VPC endpoint of type service network, per AWS's service-network-associations documentation; direct ServiceNetworkVpcAssociation is only for VPCs connected natively. This is a hardening lever when ace and appcs reach each other transitively through a hub network rather than directly.

  ServiceNetworkEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: ServiceNetwork
      VpcId: !Ref AceVpcId
      ServiceNetworkArn: !GetAtt ServiceNetwork.Arn
      SubnetIds:
        - !Ref AceSubnetId
      SecurityGroupIds:
        - !Ref AceAppSecurityGroup

Confirmed directly against AWS's own AWS::EC2::VPCEndpoint example: VpcEndpointType: ServiceNetwork is a documented value, alongside Interface, Gateway, GatewayLoadBalancer, and Resource.

Control-Plane IAM: Who Can Change Auth Policy

Everything above governs who can invoke a service, the data plane. A separate surface, easy to overlook, is who can manage VPC Lattice resources at all, the control plane: create or delete service networks, change AuthType, modify auth policies. A role permitted to call vpc-lattice:UpdateService or vpc-lattice:PutAuthPolicy can unilaterally downgrade AuthType to NONE or rewrite the auth policy, so this permission should be scoped at least as tightly as the invoke policies themselves.

  LatticeAdminPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: restrict-lattice-auth-changes
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - vpc-lattice:PutAuthPolicy
              - vpc-lattice:UpdateService
              - vpc-lattice:UpdateServiceNetwork
            Resource:
              - !GetAtt Service.Arn
              - !GetAtt ServiceNetwork.Arn
            Condition:
              StringEquals:
                aws:PrincipalTag/Team: platform-security
      Roles:
        - !Ref PlatformSecurityRoleName

The vpc-lattice: action names here follow the PascalCase-of-the-CLI-command convention confirmed directly in AWS's identity-based-policy examples (for example vpc-lattice:CreateServiceNetworkVpcAssociation mirrors the CLI's create-service-network-vpc-association exactly); PutAuthPolicy, UpdateService, and UpdateServiceNetwork were not found individually on a single enumerated action-list page, so treat these three as verified-by-naming-pattern rather than directly confirmed, worth a quick real-account check before relying on them.

Radar Assessment

AWS VPC Lattice sits in the Assess ring of the Platforms quadrant, at inner position. First studied via aws.amazon.com/vpc/lattice and six AWS blog posts (bookmarked and researched 2026-07-11). No first-person production use yet, so Assess rather than Trial. Inner position reflects a mature, actively developed service with a genuine architectural differentiator, link-local addressing that solves the overlapping-CIDR problem underlying VPC peering, and a low-friction trial path through the well-maintained Terraform provider, notwithstanding the gap in AWS's own IaC documentation. Relates to radar/techniques/AWSSaaSLens as another AWS-native multi-account architecture concern, and to radar/techniques/CloudFormationIaCGenerator as a contrasting case where AWS does provide native IaC guidance.

References

Clone this wiki locally