Lambda Fundamentals
Lambda Fundamentals
AWS Lambda runs code without provisioning or managing servers. You pay only for the compute time consumed.
Supported Runtimes
| Runtime | Version | Handler |
|---|---|---|
| Python | 3.9-3.12 | filename.handler_name |
| Node.js | 18.x, 20.x | filename.handler_name |
| Java | 11, 17, 21 | package.Class::method |
| Go | 1.x, 2.x | handler_name |
| .NET | 6, 8 | assembly::namespace.class::method |
| Ruby | 3.2 | filename.handler_name |
| Custom Runtime | Any | bootstrap |
Create a Lambda Function
# Create a Lambda function (Python)
aws lambda create-function \
--function-name my-function \
--runtime python3.12 \
--role arn:aws:iam::123456789012:role/lambda-role \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip \
--timeout 30 \
--memory-size 256 \
--environment Variables="{DB_HOST=mydb.xxxx.us-east-1.rds.amazonaws.com}"
# Update function code
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://function.zip
# Test function
aws lambda invoke \
--function-name my-function \
--payload '{"key": "value"}' \
output.json
# Check logs
aws logs describe-log-streams --log-group-name /aws/lambda/my-function
Lambda Function Structure
# Python example
import json
import boto3
def lambda_handler(event, context):
# Event contains trigger data
print(f"Event: {json.dumps(event)}")
# Context contains runtime info
print(f"Function: {context.function_name}")
print(f"Memory: {context.memory_limit_in_mb}MB")
print(f"Timeout: {context.get_remaining_time_in_millis()}ms remaining")
# Your business logic here
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Lambda Triggers and Event Sources
Lambda Triggers and Event Sources
S3 Trigger
# Add S3 trigger
aws lambda add-permission \
--function-name my-function \
--statement-id s3-trigger \
--action lambda:InvokeFunction \
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::my-bucket \
--source-account 123456789012
# Configure S3 notification
aws s3api put-bucket-notification-configuration \
--bucket my-bucket \
--notification-configuration '{
"LambdaFunctionConfigurations": [{
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
"Events": ["s3:ObjectCreated:*"],
"Filter": {
"Key": {
"FilterRules": [{"Name": "prefix", "Value": "uploads/"}]
}
}
}]
}'
API Gateway Trigger
# The API Gateway integration is configured via API Gateway
# Lambda permission is auto-created by API Gateway
DynamoDB Stream Trigger
# Event source mapping
aws lambda create-event-source-mapping \
--function-name my-function \
--event-source-arn arn:aws:dynamodb:us-east-1:xxx:table/MyTable/stream/xxx \
--starting-position LATEST \
--batch-size 100 \
--maximum-batching-window-in-seconds 5
SQS Trigger
aws lambda create-event-source-mapping \
--function-name my-function \
--event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
--batch-size 10
Event Source Types
| Source | Type | Configuration |
|---|---|---|
| S3 | Asynchronous | Bucket notification |
| API Gateway | Synchronous | Integration |
| DynamoDB Streams | Event source mapping | Stream ARN |
| SQS | Event source mapping | Queue ARN |
| SNS | Asynchronous | Topic subscription |
| CloudWatch Events | Asynchronous | Rule |
| Kinesis | Event source mapping | Stream ARN |
Lambda Layers and Package Management
Lambda Layers and Package Management
Lambda Layers
Share common code across multiple functions.
# Create a layer
zip -r layer.zip python/
aws lambda publish-layer-version \
--layer-name my-common-libs \
--description "Common Python libraries" \
--compatible-runtimes python3.12 \
--zip-file fileb://layer.zip
# Attach layer to function
aws lambda update-function-configuration \
--function-name my-function \
--layers arn:aws:lambda:us-east-1:123456789012:layer:my-common-libs:1
# List layers
aws lambda list-layer-versions --layer-name my-common-libs
Package Management
# Python - install dependencies
mkdir package
pip install -r requirements.txt -t package/
cd package
zip -r ../function.zip .
cd ..
zip function.zip lambda_function.py
# Node.js
npm install --production
zip -r function.zip node_modules/ lambda_function.js
# Java (Maven)
mvn clean package
# Target/function.jar is your deployment package
Lambda Container Images
FROM public.ecr.aws/lambda/python:3.12
COPY requirements.txt .
pip install -r requirements.txt -t ${LAMBDA_TASK_ROOT}
COPY lambda_function.py ${LAMBDA_TASK_ROOT}
CMD ["lambda_function.lambda_handler"]
# Build and push to ECR
aws ecr create-repository --repository-name my-lambda-image
# Authenticate Docker to ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
# Build and push
docker build -t my-lambda-image .
docker tag my-lambda-image:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda-image:latest
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda-image:latest
# Create function from container
aws lambda create-function \
--function-name my-container-function \
--package-type Image \
--code ImageUri=123456789012.dkr.ecr.us-east-1.amazonaws.com/my-lambda-image:latest \
--role arn:aws:iam::xxx:role/lambda-role
Lambda VPC and Networking
Lambda VPC and Networking
VPC Configuration
# Deploy Lambda in VPC
aws lambda update-function-configuration \
--function-name my-function \
--vpc-config SubnetIds=subnet-xxx,subnet-yyy,SecurityGroupIds=sg-xxx
# Environment variables for VPC
export DB_HOST=mydb.xxxx.us-east-1.rds.amazonaws.com
export REDIS_HOST=my-redis.xxx.cache.amazonaws.com
VPC Access Considerations
┌─────────────────────────────────────────────────────────────┐
│ VPC Deployment │
├─────────────────────────────────────────────────────────────┤
│ │
│ Lambda Function (in VPC) │
│ ├── Can access: │
│ │ • RDS in same VPC │
│ │ • ElastiCache in same VPC │
│ │ • EC2 in same VPC │
│ │ • Internal ALB │
│ │ │
│ ├── Needs NAT Gateway for: │
│ │ • AWS API calls (DynamoDB, S3, etc.) │
│ │ • Internet access │
│ │ │
│ └── VPC Endpoints (optional): │
│ • S3 Gateway Endpoint │
│ • DynamoDB Gateway Endpoint │
│ • Other services via Interface Endpoints │
└─────────────────────────────────────────────────────────────┘
Lambda Destinations
# Configure destinations for async invocations
aws lambda put-function-event-invoke-config \
--function-name my-function \
--maximum-retry-attempts 3 \
--maximum-event-age-in-seconds 3600 \
--destination-config '{
"OnSuccess": {
"Destination": "arn:aws:sqs:us-east-1:123456789012:success-queue"
},
"OnFailure": {
"Destination": "arn:aws:sqs:us-east-1:123456789012:failure-queue"
}
}'
Lambda Performance Optimization
Lambda Performance Optimization
Memory and CPU
# Increase memory (also increases CPU proportionally)
aws lambda update-function-configuration \
--function-name my-function \
--memory-size 1024 # 1024 MB = 1 vCPU
# Memory-CPU relationship:
# 128-1769 MB: 1 vCPU (partial)
# 1769-3538 MB: 1 vCPU
# 3539-5307 MB: 1.5 vCPU
# 5308-7076 MB: 2 vCPU
# 7077-10615 MB: 3 vCPU
Provisioned Concurrency
# Keep instances warm
aws lambda put-provisioned-concurrency-config \
--function-name my-function \
--qualifier live \
--provisioned-concurrent-executions 10
# Auto-scaling provisioned concurrency
aws application-autoscaling register-scalable-target \
--service-namespace lambda \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--resource-id function:my-function:live \
--min-capacity 1 \
--max-capacity 100
aws application-autoscaling put-scaling-policy \
--service-namespace lambda \
--scalable-dimension lambda:function:ProvisionedConcurrency \
--resource-id function:my-function:live \
--policy-name provisioned-scaling \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 0.7,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "LambdaProvisionedConcurrencyUtilization"
}
}'
SnapStart (Java)
# Enable SnapStart
aws lambda update-function-configuration \
--function-name my-java-function \
--snap-start ApplyOn=PublishedVersions
# Cold start: 3000-5000ms → 200-500ms with SnapStart
Performance Best Practices
- Minimize deployment package size (exclude boto3, use layers)
- Reuse connections (DB, HTTP clients)
- Use environment variables for configuration
- Set appropriate timeout (not too long, not too short)
- Use provisioned concurrency for latency-sensitive functions
- Enable SnapStart for Java functions
- Use ARM64 (Graviton2) for 20% better price-performance
Lambda Monitoring and Debugging
Lambda Monitoring and Debugging
CloudWatch Logs
# Get log events
aws logs get-log-events \
--log-group-name /aws/lambda/my-function \
--log-stream-name 2024/01/15/[$LATEST]xxx
# Filter logs
aws logs filter-log-events \
--log-group-name /aws/lambda/my-function \
--filter-pattern "ERROR"
# Create metric filter
aws logs put-metric-filter \
--log-group-name /aws/lambda/my-function \
--filter-name error-count \
--filter-pattern '"ERROR"' \
--metric-transformations 'metricName=ErrorCount,metricNamespace=Lambda,metricValue=1'
CloudWatch Metrics
# Key Lambda metrics
# - Invocations: Number of function invocations
# - Errors: Number of failed invocations
# - Duration: Execution time (ms)
# - Throttles: Number of throttled invocations
# - ConcurrentExecutions: Current concurrent executions
# - UnreservedConcurrentExecutions: Concurrency not in provisioned pool
aws cloudwatch get-metric-statistics \
--namespace AWS/Lambda \
--metric-name Duration \
--dimensions Name=FunctionName,Value=my-function \
--start-time $(date -u -d '1 hour ago') \
--end-time $(date -u) \
--period 300 \
--statistics Average Maximum p99
X-Ray Tracing
# Enable X-Ray tracing
aws lambda update-function-configuration \
--function-name my-function \
--tracing-config Mode=Active
# View traces
aws xray get-trace-summaries \
--start-time $(date -u -d '1 hour ago') \
--end-time $(date -u)