Skip to content

Lambda VPC — Accessing Resources in a Virtual Private Cloud

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Lambda VPC. We cover key concepts, practical examples, and best practices to help you master this topic.

AWS Lambda functions can access resources inside a Virtual Private Cloud (VPC) by attaching to VPC subnets and security groups, enabling secure connections to RDS, ElastiCache, and internal services.

What You'll Learn

By the end of this lesson you will understand how to configure Lambda for VPC access, connect to RDS databases and ElastiCache, manage VPC cold starts, and use VPC endpoints for AWS services.

Why It Matters

Many production serverless applications need access to database services like RDS, caching services like ElastiCache, or internal APIs running on EC2. Without VPC configuration, Lambda cannot reach these private resources.

Real-World Use

DodaTech's analytics platform uses Lambda functions in a VPC to query an RDS PostgreSQL database for historical data and cache results in ElastiCache Redis. The VPC configuration keeps all data traffic within the private network.

flowchart TD
    L[AWS Lambda VPC] --> S[VPC Subnet]
    S --> RDS[RDS Database]
    S --> EC[ElastiCache Redis]
    S --> I[Internal API on EC2]
    L --> E[VPC Endpoint]
    E --> SSM[SSM Parameter Store]
    style L fill:#f90,color:#fff

Configuring VPC Access

Lambda VPC configuration requires specifying one or more subnets and security groups. Lambda creates an elastic network interface (ENI) in each subnet.

# vpc_config.py
# Understanding Lambda VPC configuration

class VPCConfig:
    def __init__(self, subnet_ids, security_group_ids):
        self.subnets = subnet_ids
        self.security_groups = security_group_ids
    
    def describe(self):
        print("Lambda VPC Configuration:")
        print(f"  Subnets: {', '.join(self.subnets)}")
        print(f"  Security Groups: {', '.join(self.security_groups)}")
        print(f"  ENIs Created: {len(self.subnets)} (one per subnet)")
        print("  Route Table: Routes traffic within VPC")

vpc = VPCConfig(
    subnet_ids=["subnet-abc123", "subnet-def456", "subnet-ghi789"],
    security_group_ids=["sg-db-access"]
)
vpc.describe()

Expected output:

Lambda VPC Configuration:
  Subnets: subnet-abc123, subnet-def456, subnet-ghi789
  Security Groups: sg-db-access
  ENIs Created: 3 (one per subnet)
  Route Table: Routes traffic within VPC

Connecting to RDS

Lambda can connect to RDS using standard database drivers. The security group must allow inbound connections from Lambda on the database port.

# rds_connection.py
# Connecting to RDS from Lambda

import json
import os

def lambda_handler(event, context):
    db_host = os.environ.get("DB_HOST", "my-db.cluster-abc123.us-east-1.rds.amazonaws.com")
    db_port = os.environ.get("DB_PORT", "5432")
    db_name = os.environ.get("DB_NAME", "appdb")
    db_user = os.environ.get("DB_USER", "app_user")
    
    print(f"Connecting to PostgreSQL at {db_host}:{db_port}/{db_name}")
    print(f"Authenticating as {db_user}")
    
    conn = connect_with_pool(db_host, db_port, db_name, db_user)
    result = query_users(conn)
    
    return {"statusCode": 200, "body": json.dumps({"users": result})}

def connect_with_pool(host, port, db_name, user):
    print("  Creating connection pool (reused across warm starts)")
    return {"connected": True, "host": host, "total_connections": 5}

def query_users(conn):
    print("  Executing: SELECT id, name, email FROM users LIMIT 10")
    return [
        {"id": 1, "name": "Alice", "email": "alice@example.com"},
        {"id": 2, "name": "Bob", "email": "bob@example.com"}
    ]

print(lambda_handler({}, None)["body"])

Expected output:

Connecting to PostgreSQL at my-db...rds.amazonaws.com:5432/appdb
Authenticating as app_user
  Creating connection pool (reused across warm starts)
  Executing: SELECT id, name, email FROM users LIMIT 10
[{"id": 1, "name": "Alice", "email": "alice@example.com"}, {"id": 2, "name": "Bob", "email": "bob@example.com"}]

VPC Cold Start Impact

VPC-configured Lambda functions have additional cold start latency because Lambda must create and attach an elastic network interface.

# vpc_cold_start.py
# VPC cold start measurement

import time

def measure_vpc_cold_start():
    start = time.time()
    
    print("[VPC Cold Start] Requesting ENI allocation...")
    time.sleep(1.0)
    print("[VPC Cold Start] Attaching ENI to Lambda...")
    time.sleep(0.5)
    print("[VPC Cold Start] Configuring routing...")
    time.sleep(0.3)
    print("[VPC Cold Start] Initializing runtime...")
    time.sleep(0.2)
    
    elapsed = (time.time() - start) * 1000
    return elapsed

def measure_no_vpc_cold_start():
    start = time.time()
    
    print("[No VPC Cold Start] Initializing runtime...")
    time.sleep(0.2)
    
    elapsed = (time.time() - start) * 1000
    return elapsed

vpc = measure_vpc_cold_start()
no_vpc = measure_no_vpc_cold_start()

print(f"\nVPC cold start: {vpc:.0f}ms")
print(f"No VPC cold start: {no_vpc:.0f}ms")
print(f"VPC overhead: {vpc - no_vpc:.0f}ms")

Expected output:

[VPC Cold Start] Requesting ENI allocation...
[VPC Cold Start] Attaching ENI to Lambda...
[VPC Cold Start] Configuring routing...
[VPC Cold Start] Initializing runtime...
VPC cold start: 2000ms
No VPC cold start: 200ms
VPC overhead: 1800ms

VPC Endpoints

Use VPC endpoints to access AWS services (S3, DynamoDB, SQS) without traversing the public internet.

# vpc_endpoints.py
# VPC endpoints for AWS services

def describe_vpc_endpoints():
    endpoints = {
        "s3": {
            "type": "Gateway",
            "service": "com.amazonaws.us-east-1.s3",
            "benefit": "Private access to S3 without NAT gateway"
        },
        "dynamodb": {
            "type": "Gateway",
            "service": "com.amazonaws.us-east-1.dynamodb",
            "benefit": "Private access to DynamoDB"
        },
        "sqs": {
            "type": "Interface",
            "service": "com.amazonaws.us-east-1.sqs",
            "benefit": "Private access to SQS"
        },
        "secretsmanager": {
            "type": "Interface",
            "service": "com.amazonaws.us-east-1.secretsmanager",
            "benefit": "Private access to Secrets Manager"
        }
    }
    
    for name, config in endpoints.items():
        print(f"{name:15s} {config['type']:10s} -> {config['benefit']}")

describe_vpc_endpoints()

Common Mistakes

  1. Not having a NAT gateway for internet access: Lambda in a private subnet needs a NAT gateway to access the internet. Without it, external API calls fail.

  2. Creating too many subnets: Each subnet creates an ENI. More subnets increase ENI creation time and cold start latency. Use 2-3 subnets in different AZs.

  3. Using VPC when not needed: If your Lambda only accesses DynamoDB and S3, use VPC endpoints instead of putting Lambda in a VPC.

  4. Security group too restrictive: The security group must allow outbound connections to RDS. Without egress rules, connections time out.

  5. Forgetting RDS proxy for connection pooling: Lambda scale creates many database connections. Use RDS Proxy to manage connection pooling.

Practice Questions

  1. Why does VPC configuration increase cold start latency? Lambda must create and attach an elastic network interface to the execution environment before invocation.

  2. How does Lambda access the internet from a VPC? The function must be in a private subnet with a route to a NAT gateway, or use a public subnet.

  3. What is RDS Proxy and why use it with Lambda? RDS Proxy manages database connection pooling, preventing Lambda from exhausting database connections during scaling.

  4. How many subnets should you configure for Lambda VPC? 2-3 subnets across different Availability Zones for high availability.

  5. Challenge: Design a VPC architecture for Lambda functions that need access to RDS, ElastiCache, and S3 (via VPC endpoint) without internet access.

FAQ

Can Lambda access the internet from a VPC?

Yes, if the function is in a private subnet with a NAT gateway, or in a public subnet with an internet gateway.

Do all functions in a VPC need VPC configuration?

No. Only functions that need to access private VPC resources need VPC configuration.

How long do Lambda ENIs persist?

ENIs persist for the lifetime of the execution environment, typically several hours of inactivity before cleanup.

Can I use VPC endpoints with Lambda?

Yes. VPC endpoints enable private access to AWS services without NAT gateways or internet.

Does VPC configuration affect Lambda pricing?

No. You pay only for the function execution. ENI costs are covered by Lambda.

Mini Project

Create a Lambda function in a VPC that connects to RDS PostgreSQL, queries a users table, caches the result in ElastiCache Redis, and returns the data. Include connection pooling with RDS Proxy.

import json

def lambda_handler(event, context):
    db_host = "database.cluster-abc.us-east-1.rds.amazonaws.com"
    cache_host = "redis-cluster.abc.0001.use1.cache.amazonaws.com"
    
    print(f"Checking cache at {cache_host}")
    cached = None
    if cached:
        print("Cache HIT - returning cached data")
        return {"statusCode": 200, "body": cached}
    
    print("Cache MISS - querying database")
    print(f"Connecting to RDS Proxy at {db_host}")
    data = query_users()
    
    print("Storing result in cache")
    return {"statusCode": 200, "body": json.dumps(data)}

def query_users():
    return [{"id": 1, "name": "Alice", "email": "alice@example.com"}]

print(lambda_handler({}, None)["body"])

What's Next

Next: Lambda Monitoring (CloudWatch) for Observability.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro