Lambda in a VPC: reaching the internet and AWS services
Attaching a Lambda function to a VPC gives it private network access and takes away its internet access. What each side needs — execution role ENI permissions, private subnets with a NAT gateway or VPC endpoints, security groups — with a known-good setup and known-bad ones with their symptoms (usually a timeout with no error).
markdownpatternv4WR7Y-0CMKstage: buildtrust: officialservice: lambdaservice: vpcinterface: cliinterface: iacLambda VPCLambda internet accessLambda NAT gatewayLambda public subnetAWSLambdaVPCAccessExecutionRoleLambda VPC endpointLambda timeout VPCENILimitReachedExceptionSubnetIPAddressLimitReachedExceptionEC2AccessDeniedExceptionvpc-config
Lambda in a VPC
Only attach a function to a VPC if it must reach private resources, such as a database, an internal service or a private endpoint. Once it is attached, the function has no internet access and no public IP, even in a public subnet. Every call to an AWS API or the internet needs a NAT gateway or a VPC endpoint. Without one, the call hangs until Task timed out.
What crosses the handoff
| Side | Provides / expects |
|---|---|
| Lambda | Creates network interfaces in the subnets you list, using the execution role. That needs the ec2:CreateNetworkInterface/Describe…/Delete… permissions in AWSLambdaVPCAccessExecutionRole. The role grants the right to create interfaces, not any network path. |
| VPC | Subnets with free IP addresses, security groups that allow the function's outbound traffic, and routes: private subnets → NAT gateway (a zonal one in a public subnet, or a regional one that needs no public subnet) → internet gateway, and/or VPC endpoints for the AWS services the function calls. |
Known-good
- Two or more private subnets in different Availability Zones, each with a route
0.0.0.0/0 → nat-…. A zonal NAT gateway sits in a public subnet whose route goes to the internet gateway; a regional NAT gateway (create-nat-gateway --vpc-id … --availability-mode regional) needs no public subnet and serves every AZ with one ID (reference/vpc/routing-and-gateways.md). - A security group for the function with outbound HTTPS, plus whatever the database needs. Allow inbound on the database's group from the function's group.
- The execution role has
AWSLambdaVPCAccessExecutionRole(or equivalent) and the function's own permissions. - Attach:
aws lambda update-function-configuration --function-name <fn> \
--vpc-config SubnetIds=<subnet-a>,<subnet-b>,SecurityGroupIds=<sg>
aws lambda wait function-updated-v2 --function-name <fn>
- Optional, to avoid NAT for AWS traffic: VPC endpoints (gateway endpoints for S3 and DynamoDB; interface endpoints for others such as
secretsmanager,sqs,sts) with private DNS on. Their security groups must allow 443 from the function's group. Endpoint policies are a second policy layer (patterns/iam-to-vpc-endpoints.md).
Known-bad
| Configuration | Symptom |
|---|---|
| Function in a public subnet, expecting internet | Task timed out after N seconds on the first outbound call: Lambda never gets a public IP |
| Private subnets with no NAT route and no endpoint for the service | Same timeout. No error from the SDK unless its own timeout is shorter |
| Gateway endpoint for S3 created but not associated with the function's route tables | S3 calls time out; other calls work |
| Interface endpoint without private DNS | The SDK resolves the public name and times out |
| Execution role without the ENI permissions | Update or invoke fails with EC2AccessDeniedException (502); the function's state shows the reason |
| Subnets nearly full | SubnetIPAddressLimitReachedException (502) on invoke or scale-out |
| Many functions or subnets × security group combinations | ENILimitReachedException (502): the per-VPC Lambda network-interface quota is reached |
| A subnet or security group deleted after configuration | InvalidSubnetIDException / InvalidSecurityGroupIDException (502) |
| Security group allows no outbound traffic | Timeouts on every connection |
Which side is wrong?
- Timeout with no error → the network side: routes, NAT, endpoints, security group egress. Reachability Analyzer from the function's network interface names the blocking layer (
guides/vpc/diagnose-connection-timeout.md). Check what the function calls, thenaws ec2 describe-route-tables --filters Name=association.subnet-id,Values=<subnet>. - A 502 exception naming EC2, ENI or subnets → the Lambda side's set-up: the execution role, subnet IP capacity or quotas (
reference/lambda/errors.md). - The connection is refused by the database → the database's security group does not allow the function's group.
Design notes
- Make SDK client timeouts shorter than the function timeout, so a missing route produces an error message rather than a bare
Task timed out. - Updating VPC settings puts the function into a
Pendingupdate. Wait before invoking (ResourceConflictExceptionotherwise). - To detach, use
--vpc-config SubnetIds=[],SecurityGroupIds=[].