π Tired of managing complex VPC peering or Transit Gateway configurations? Discover how AWS VPC Lattice simplifies service-to-service communication across VPCs.
NetworkingMadeSimple πβ¨
π‘In modern cloud architectures, applications are often distributed across multiple VPCs for better isolation and security. However, this creates
challenges for service-to-service communication. Traditional solutions like VPC peering or Transit Gateway can be complex to manage and scale.
AWS VPC Lattice offers a simpler approach by providing a fully managed service networking solution. In this post, I'll walk through a practical proof
of concept (POC) that demonstrates how VPC Lattice can connect services across different VPCs without complex networking configurations.
The Problem: Cross-VPC Service Communication
π Consider this common scenario:
β’ SpokeA VPC: Contains your application logic (Lambda functions)
β’ SpokeC VPC: Contains your backend services (web servers)
π§± Traditionally, you'd need to set up VPC peering, Transit Gateway, or use an Application Load Balancer (ALB) to enable communication between these VPCs.
Each approach has its own complexities and limitations.
The Solution: VPC Lattice
VPC Lattice provides a service-oriented approach to networking. Instead of focusing on network connectivity, you register services and let VPC Lattice
handle the discovery and routing.
Our POC demonstrates this by connecting a Lambda function in SpokeA VPC to an Apache web server in SpokeC VPC through VPC Lattice.
POC Architecture
- SpokeC VPC: Contains an EC2 instance running Apache
- SpokeA VPC: Contains a Lambda function that accesses the Apache server
- VPC Lattice: Connects the two VPCs and enables service discovery
Step-by-Step Implementation
1. Create a VPC Lattice Service Network
bash
$ aws vpc-lattice create-service-network --name "poc-service-network" --region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:servicenetwork/sn-0735c8dcd85f31ba0",
"createdAt": "2025-07-06T13:34:38.065000+00:00",
"id": "sn-0735c8dcd85f31ba0",
"lastUpdatedAt": "2025-07-06T13:34:38.065000+00:00",
"name": "poc-service-network",
"numberOfAssociatedResourceConfigurations": 0,
"numberOfAssociatedServices": 0,
"numberOfAssociatedVPCs": 0
}
2. Associate VPCs with the Service Network
bash
$ aws vpc-lattice create-service-network-vpc-association \
--service-network-identifier sn-0735c8dcd85f31ba0 \
--vpc-identifier vpc-09e69971ba778dc66 \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:servicenetworkvpcassociation/snva-0b31c3c150f75e0cd",
"createdBy": "XXYY112233",
"id": "snva-0b31c3c150f75e0cd",
"status": "CREATE_IN_PROGRESS"
}
$ aws vpc-lattice create-service-network-vpc-association \
--service-network-identifier sn-0735c8dcd85f31ba0 \
--vpc-identifier vpc-06bb9f3453465ee95 \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:servicenetworkvpcassociation/snva-088beb43dc9cc2e88",
"createdBy": "XXYY1122333",
"id": "snva-088beb43dc9cc2e88",
"status": "CREATE_IN_PROGRESS"
}
3. Create a VPC Lattice Service for the Apache Server
bash
$ aws vpc-lattice create-service \
--name "apache-service" \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:service/svc-0b5ef28909b938204",
"authType": "NONE",
"dnsEntry": {
"domainName": "apache-service-0b5ef28909b938204.7d67968.vpc-lattice-svcs.us-east-1.on.aws",
"hostedZoneId": "Z0681547Z82L3THDFSCZ"
},
"id": "svc-0b5ef28909b938204",
"name": "apache-service",
"status": "CREATE_IN_PROGRESS"
}
4. Create a Target Group for the Apache EC2 Instance
bash
$ aws vpc-lattice create-target-group \
--name "apache-target-group" \
--type INSTANCE \
--config '{"port": 80, "protocol": "HTTP", "vpcIdentifier": "vpc-09e69971ba778dc66"}' \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:targetgroup/tg-08a1d70cb62776f59",
"config": {
"healthCheck": {
"enabled": true,
"healthCheckIntervalSeconds": 30,
"healthCheckTimeoutSeconds": 5,
"healthyThresholdCount": 5,
"matcher": {
"httpCode": "200"
},
"path": "/",
"protocol": "HTTP",
"protocolVersion": "HTTP1",
"unhealthyThresholdCount": 2
},
"ipAddressType": "IPV4",
"port": 80,
"protocol": "HTTP",
"protocolVersion": "HTTP1",
"vpcIdentifier": "vpc-09e69971ba778dc66"
},
"id": "tg-08a1d70cb62776f59",
"name": "apache-target-group",
"status": "CREATE_IN_PROGRESS",
"type": "INSTANCE"
}
5. Register the EC2 Instance with the Target Group
bash
$ aws vpc-lattice register-targets \
--target-group-identifier tg-08a1d70cb62776f59 \
--targets '[{"id": "i-012ab2d1599a3a7f5", "port": 80}]' \
--region us-east-1
{
"successful": [
{
"id": "i-012ab2d1599a3a7f5",
"port": 80
}
],
"unsuccessful": []
}
6. Create a Listener for the Service
bash
$ aws vpc-lattice create-listener \
--service-identifier svc-0b5ef28909b938204 \
--name "http-listener" \
--protocol HTTP \
--port 80 \
--default-action '{"forward": {"targetGroups": [{"targetGroupIdentifier": "tg-08a1d70cb62776f59"}]}}' \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:service/svc-0b5ef28909b938204/listener/listener-0db2fbc883a854bf3",
"defaultAction": {
"forward": {
"targetGroups": [
{
"targetGroupIdentifier": "tg-08a1d70cb62776f59",
"weight": 100
}
]
}
},
"id": "listener-0db2fbc883a854bf3",
"name": "http-listener",
"port": 80,
"protocol": "HTTP",
"serviceArn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:service/svc-0b5ef28909b938204",
"serviceId": "svc-0b5ef28909b938204"
}
7. Associate the Service with the Service Network
bash
$ aws vpc-lattice create-service-network-service-association \
--service-network-identifier sn-0735c8dcd85f31ba0 \
--service-identifier svc-0b5ef28909b938204 \
--region us-east-1
{
"arn": "arn:aws:vpc-lattice:us-east-1:XXYY112233:servicenetworkserviceassociation/snsa-0091d77572ee6e123",
"createdBy": "XXYY112233",
"dnsEntry": {
"domainName": "apache-service-0b5ef28909b938204.7d67968.vpc-lattice-svcs.us-east-1.on.aws",
"hostedZoneId": "Z0681547Z82L3THDFSCZ"
},
"id": "snsa-0091d77572ee6e123",
"status": "CREATE_IN_PROGRESS"
}
8. Create a Lambda Function to Access the Apache Server
python
import json
import urllib.request
import os
def lambda_handler(event, context):
# Get the VPC Lattice service DNS name from environment variable
service_url = os.environ['SERVICE_URL']
try: # Make a request to the Apache server through VPC Lattice with urllib.request.urlopen(f"http://{service_url}") as response: html = response.read().decode('utf-8') return { 'statusCode': 200, 'body': json.dumps({ 'message': 'Successfully accessed Apache server through VPC Lattice', 'html_snippet': html[:500] + '...' if len(html) > 500 else html }) } except Exception as e: return { 'statusCode': 500, 'body': json.dumps({ 'message': 'Error accessing Apache server', 'error': str(e) }) }
bash
$ aws lambda create-function \
--function-name VPCLatticeApacheAccess \
--runtime python3.9 \
--role arn:aws:iam::XXYY112233:role/LatticeAccessRole \
--handler lambda_function.lambda_handler \
--zip-file fileb://~/lambda_function.zip \
--vpc-config "SubnetIds=subnet-02f8a7734c22ff7a5,subnet-0139b62cbd4fc7768,SecurityGroupIds=sg-0760a256370568790" \
--environment "Variables={SERVICE_URL=apache-service-0b5ef28909b938204.7d67968.vpc-lattice-svcs.us-east-1.on.aws}" \
--region us-east-1
9. Test the Lambda Function
bash
$ aws lambda invoke \
--function-name VPCLatticeApacheAccess \
--payload '{}' \
--region us-east-1 \
response.json && cat response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
{"statusCode": 200, "body": "{\"message\": \"Successfully accessed Apache server through VPC Lattice\", \"html_snippet\": \"test web\n\"}"}
10. Make the Lambda Function Publicly Accessible (Optional)
bash
$ aws apigateway create-rest-api \
--name "VPCLatticeApacheAccess-API" \
--region us-east-1
$ aws apigateway create-resource \
--rest-api-id xxyyzzzxx \
--parent-id ju51yslurg \
--path-part "apache" \
--region us-east-1
$ aws apigateway put-method \
--rest-api-id xxyyzzzxx \
--resource-id 129hegto \
--http-method GET \
--authorization-type NONE \
--region us-east-1
$ aws apigateway put-integration \
--rest-api-id xxyyzzxx \
--resource-id 129hegto \
--http-method GET \
--type AWS_PROXY \
--integration-http-method POST \
--uri arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:XXYY112233:function:VPCLatticeApacheAccess/invocations \
--region us-east-1
$ aws apigateway create-deployment \
--rest-api-id xxyyxxzz \
--stage-name prod \
--region us-east-1
Test the public endpoint:
bash
$ curl -s https://xxxyyyxxx.execute-api.us-east-1.amazonaws.com/prod/apache
{"message": "Successfully accessed Apache server through VPC Lattice", "html_snippet": "test web\n"}
When to Use VPC Lattice with Lambda Instead of ALB
β ## When to Use VPC Lattice Instead of ALB
While Application Load Balancers (ALBs) are a common choice for routing traffic to backend services, VPC Lattice with Lambda offers several advantages in specific scenarios:
1. Multi-VPC Architectures π
VPC Lattice Advantage: VPC Lattice is designed for multi-VPC environments. It eliminates the need for complex networking setups like VPC peering or
Transit Gateway.
Business Case: Organizations with strict isolation requirements between different business units or applications that still need to communicate with
each other.
2. Service Discovery π§
VPC Lattice Advantage: Built-in service discovery through DNS and service mesh capabilities.
Business Case: Microservices architectures where services need to discover and communicate with each other dynamically.
3. Fine-Grained Access Control π
VPC Lattice Advantage: Supports IAM-based authentication and authorization at the service level.
Business Case: Environments with strict security requirements where you need to control which services can communicate with each other.
4. Serverless-First Architectures βοΈβ‘
VPC Lattice Advantage: Seamless integration with Lambda functions, eliminating the need for maintaining networking infrastructure.
Business Case: Organizations embracing serverless architectures that need to connect to legacy or containerized services.
5. Cost Optimization for Variable Traffic π°π
VPC Lattice Advantage: Pay-per-use pricing model with no minimum fees or idle charges.
Business Case: Applications with variable or unpredictable traffic patterns where maintaining always-on ALBs would be costly.
ποΈ Real-World Use Cases
1.π¦ Financial Services: Connecting customer-facing applications with backend processing systems while maintaining strict isolation between environments.
2.π₯ Healthcare: Enabling secure communication between patient-facing applications and protected health information (PHI) systems across different
security domains.
3.π Retail: Connecting inventory management systems with order processing services across different business units or acquisitions.
4.π§βπ» SaaS Platforms: Providing isolated environments for each customer while enabling shared services to communicate across tenant boundaries.
Conclusion
VPC Lattice provides a simpler, more service-oriented approach to networking in AWS. By focusing on services rather than network connectivity, it
eliminates much of the complexity associated with traditional networking solutions.
Our POC demonstrates how VPC Lattice can connect services across different VPCs with minimal configuration. The Lambda function in SpokeA VPC can
seamlessly access the Apache server in SpokeC VPC through VPC Lattice, without any direct network connectivity between the VPCs.
For organizations with multi-VPC architectures, microservices, or serverless applications, VPC Lattice offers a compelling alternative to traditional
networking approaches. It simplifies service-to-service communication, enhances security through fine-grained access control, and reduces operational
overhead.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π¬ Have you tried VPC Lattice in your environment? What challenges did you face with cross-VPC communication?
π Drop your thoughts and war stories in the comments! Letβs learn together. ππ§΅
Top comments (0)