2026-01-27 17:35:45 -05:00
---
name : aws-lambda
description : Build and deploy serverless functions on AWS Lambda. Configure triggers, manage permissions, and optimize performance. Use when implementing serverless applications.
license : MIT
metadata :
author : devops-skills
version : "1.0"
---
# AWS Lambda
2026-03-24 18:02:50 -04:00
Build serverless applications with AWS Lambda, covering function creation, event sources, layers, SAM templates, and cold start optimization.
2026-01-27 17:35:45 -05:00
2026-03-24 18:02:50 -04:00
## When to Use This Skill
- Building event-driven applications triggered by API Gateway, S3, SQS, or EventBridge
- Running scheduled tasks (cron) without managing servers
- Processing data streams from Kinesis or DynamoDB
- Building lightweight APIs with API Gateway or function URLs
- Implementing webhooks, Slack bots, or automation scripts
- Reducing compute costs for intermittent or bursty workloads
## Prerequisites
- AWS CLI v2 installed and configured
- IAM permissions: `lambda:*` , `iam:PassRole` , `logs:*` , `apigateway:*` , `s3:*`
- Python 3.11+, Node.js 20+, or another supported runtime installed locally
- (Optional) AWS SAM CLI for local development and deployment
## Create and Deploy a Function
2026-01-27 17:35:45 -05:00
```bash
2026-03-24 18:02:50 -04:00
# Create a deployment package
cd my-function
zip -r function .zip app.py
# Create the Lambda function
2026-01-27 17:35:45 -05:00
aws lambda create-function \
2026-03-24 18:02:50 -04:00
--function-name my-api-handler \
--runtime python3.12 \
2026-01-27 17:35:45 -05:00
--handler app.handler \
2026-03-24 18:02:50 -04:00
--role arn:aws:iam::123456789012:role/LambdaExecRole \
--zip-file fileb://function.zip \
--memory-size 256 \
--timeout 30 \
--environment 'Variables={STAGE=production,LOG_LEVEL=INFO}' \
--architectures arm64 \
--tracing-config Mode = Active \
--tags '{"Team":"backend","Environment":"production"}'
# Update function code
aws lambda update-function-code \
--function-name my-api-handler \
2026-01-27 17:35:45 -05:00
--zip-file fileb://function.zip
2026-03-24 18:02:50 -04:00
# Update function configuration
aws lambda update-function-configuration \
--function-name my-api-handler \
--memory-size 512 \
--timeout 60 \
--environment 'Variables={STAGE=production,LOG_LEVEL=WARNING}'
# Publish a version (immutable snapshot)
aws lambda publish-version \
--function-name my-api-handler \
--description "v1.2.0 - added rate limiting"
# Create an alias pointing to the version
aws lambda create-alias \
--function-name my-api-handler \
--name live \
--function-version 3
# Weighted alias for canary deployments (90% v3, 10% v4)
aws lambda update-alias \
--function-name my-api-handler \
--name live \
--function-version 4 \
--routing-config '{"AdditionalVersionWeights":{"3":0.9}}'
2026-01-27 17:35:45 -05:00
```
2026-03-24 18:02:50 -04:00
## Function Code Examples
2026-01-27 17:35:45 -05:00
```python
2026-03-24 18:02:50 -04:00
# app.py - API Gateway handler with structured logging
2026-01-27 17:35:45 -05:00
import json
2026-03-24 18:02:50 -04:00
import logging
import os
logger = logging . getLogger ()
logger . setLevel ( os . environ . get ( "LOG_LEVEL" , "INFO" ))
2026-01-27 17:35:45 -05:00
def handler ( event , context ):
2026-03-24 18:02:50 -04:00
"""Handle API Gateway proxy event."""
logger . info ( "Request: %s %s " , event [ "httpMethod" ], event [ "path" ])
try :
body = json . loads ( event . get ( "body" , " {} " ))
result = process_request ( body )
return {
"statusCode" : 200 ,
"headers" : {
"Content-Type" : "application/json" ,
"X-Request-Id" : context . aws_request_id
},
"body" : json . dumps ( result )
}
except ValueError as e :
logger . warning ( "Validation error: %s " , e )
return { "statusCode" : 400 , "body" : json . dumps ({ "error" : str ( e )})}
except Exception as e :
logger . exception ( "Unhandled error" )
return { "statusCode" : 500 , "body" : json . dumps ({ "error" : "Internal server error" })}
def process_request ( body ):
return { "message" : "OK" , "data" : body }
```
```python
# sqs_processor.py - SQS batch processor with partial failure reporting
import json
import logging
logger = logging . getLogger ()
logger . setLevel ( "INFO" )
def handler ( event , context ):
"""Process SQS messages with partial batch failure reporting."""
failed_ids = []
for record in event [ "Records" ]:
try :
body = json . loads ( record [ "body" ])
logger . info ( "Processing message: %s " , record [ "messageId" ])
process_message ( body )
except Exception as e :
logger . error ( "Failed message %s : %s " , record [ "messageId" ], e )
failed_ids . append ( record [ "messageId" ])
# Return failed items so only those get retried
2026-01-27 17:35:45 -05:00
return {
2026-03-24 18:02:50 -04:00
"batchItemFailures" : [
{ "itemIdentifier" : msg_id } for msg_id in failed_ids
]
2026-01-27 17:35:45 -05:00
}
2026-03-24 18:02:50 -04:00
def process_message ( body ):
pass # your logic here
2026-01-27 17:35:45 -05:00
```
2026-03-24 18:02:50 -04:00
## Lambda Layers
2026-01-27 17:35:45 -05:00
```bash
2026-03-24 18:02:50 -04:00
# Build a layer for Python dependencies
mkdir -p layer/python
pip install requests boto3-stubs -t layer/python/
cd layer
zip -r ../my-layer.zip python/
2026-01-27 17:35:45 -05:00
2026-03-24 18:02:50 -04:00
# Publish the layer
aws lambda publish-layer-version \
--layer-name common-deps \
--description "Shared Python dependencies" \
--zip-file fileb://my-layer.zip \
--compatible-runtimes python3.11 python3.12 \
--compatible-architectures arm64 x86_64
# Attach layer to a function
aws lambda update-function-configuration \
--function-name my-api-handler \
--layers "arn:aws:lambda:us-east-1:123456789012:layer:common-deps:1"
# List available layers
aws lambda list-layers --compatible-runtime python3.12
```
## Event Source Mappings
```bash
# SQS trigger with batch processing
aws lambda create-event-source-mapping \
--function-name sqs-processor \
--event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
--batch-size 10 \
--maximum-batching-window-in-seconds 5 \
--function-response-types ReportBatchItemFailures
# DynamoDB Streams trigger
aws lambda create-event-source-mapping \
--function-name stream-processor \
--event-source-arn arn:aws:dynamodb:us-east-1:123456789012:table/my-table/stream/2026-01-01T00:00:00.000 \
--batch-size 100 \
--starting-position LATEST \
--maximum-retry-attempts 3 \
--bisect-batch-on-function-error \
--destination-config '{"OnFailure":{"Destination":"arn:aws:sqs:us-east-1:123456789012:dlq"}}'
# S3 event notification (via Lambda permission + S3 config)
2026-01-27 17:35:45 -05:00
aws lambda add-permission \
2026-03-24 18:02:50 -04:00
--function-name image-processor \
--statement-id s3-trigger \
2026-01-27 17:35:45 -05:00
--action lambda:InvokeFunction \
2026-03-24 18:02:50 -04:00
--principal s3.amazonaws.com \
--source-arn arn:aws:s3:::my-uploads-bucket \
--source-account 123456789012
aws s3api put-bucket-notification-configuration \
--bucket my-uploads-bucket \
--notification-configuration '{
"LambdaFunctionConfigurations": [{
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:image-processor",
"Events": ["s3:ObjectCreated:*"],
"Filter": {"Key": {"FilterRules": [{"Name": "suffix", "Value": ".jpg"}]}}
}]
}'
# Schedule with EventBridge (cron)
aws events put-rule \
--name daily-cleanup \
--schedule-expression "cron(0 2 * * ? *)" \
--state ENABLED
aws lambda add-permission \
--function-name daily-cleanup \
--statement-id eventbridge \
--action lambda:InvokeFunction \
--principal events.amazonaws.com \
--source-arn arn:aws:events:us-east-1:123456789012:rule/daily-cleanup
aws events put-targets \
--rule daily-cleanup \
--targets '[{"Id":"1","Arn":"arn:aws:lambda:us-east-1:123456789012:function:daily-cleanup"}]'
2026-01-27 17:35:45 -05:00
```
2026-03-24 18:02:50 -04:00
## Function URLs (No API Gateway Needed)
2026-01-27 17:35:45 -05:00
```bash
2026-03-24 18:02:50 -04:00
# Create a function URL (public HTTPS endpoint)
aws lambda create-function-url-config \
--function-name my-api-handler \
--auth-type NONE \
--cors '{
"AllowOrigins": ["https://myapp.com"],
"AllowMethods": ["GET", "POST"],
"AllowHeaders": ["Content-Type"],
"MaxAge": 86400
}'
2026-01-27 17:35:45 -05:00
2026-03-24 18:02:50 -04:00
# Grant public invoke for function URL
aws lambda add-permission \
--function-name my-api-handler \
--statement-id function -url-public \
--action lambda:InvokeFunctionUrl \
--principal "*" \
--function-url-auth-type NONE
2026-01-27 17:35:45 -05:00
```
2026-03-24 18:02:50 -04:00
## Cold Start Optimization
2026-01-27 17:35:45 -05:00
2026-03-24 18:02:50 -04:00
```bash
# Enable provisioned concurrency to eliminate cold starts
aws lambda put-provisioned-concurrency-config \
--function-name my-api-handler \
--qualifier live \
--provisioned-concurrent-executions 10
# Set reserved concurrency (throttle limit)
aws lambda put-function-concurrency \
--function-name my-api-handler \
--reserved-concurrent-executions 100
# Enable SnapStart for Java functions (near-zero cold starts)
aws lambda update-function-configuration \
--function-name my-java-handler \
--snap-start '{"ApplyOn": "PublishedVersions"}'
aws lambda publish-version --function-name my-java-handler
```
Cold start reduction tips:
- Use `arm64` architecture (Graviton) for faster init and lower cost
- Minimize deployment package size; use layers for large dependencies
- Initialize SDK clients outside the handler function
- Avoid VPC unless required (VPC cold starts are longer)
- Use provisioned concurrency for latency-sensitive paths
## SAM Template
```yaml
# template.yaml - AWS SAM application
AWSTemplateFormatVersion : '2010-09-09'
Transform : AWS::Serverless-2016-10-31
Description : My serverless API
Globals :
Function :
Runtime : python3.12
Architectures : [ arm64]
MemorySize : 256
Timeout : 30
Tracing : Active
Environment :
Variables :
STAGE : !Ref Stage
LOG_LEVEL : INFO
Parameters :
Stage :
Type : String
Default : dev
AllowedValues : [ dev, staging, prod]
Resources :
ApiFunction :
Type : AWS::Serverless::Function
Properties :
FunctionName : !Sub "${Stage}-api-handler"
Handler : app.handler
CodeUri : src/
Layers :
- !Ref DepsLayer
Events :
GetItems :
Type : Api
Properties :
Path : /items
Method : get
PostItem :
Type : Api
Properties :
Path : /items
Method : post
Policies :
- DynamoDBCrudPolicy :
TableName : !Ref ItemsTable
QueueProcessor :
Type : AWS::Serverless::Function
Properties :
FunctionName : !Sub "${Stage}-queue-processor"
Handler : sqs_processor.handler
CodeUri : src/
Events :
SQSEvent :
Type : SQS
Properties :
Queue : !GetAtt ProcessingQueue.Arn
BatchSize : 10
FunctionResponseTypes :
- ReportBatchItemFailures
DepsLayer :
Type : AWS::Serverless::LayerVersion
Properties :
LayerName : common-deps
ContentUri : layer/
CompatibleRuntimes :
- python3.12
ItemsTable :
Type : AWS::DynamoDB::Table
Properties :
TableName : !Sub "${Stage}-items"
BillingMode : PAY_PER_REQUEST
AttributeDefinitions :
- AttributeName : id
AttributeType : S
KeySchema :
- AttributeName : id
KeyType : HASH
ProcessingQueue :
Type : AWS::SQS::Queue
Properties :
QueueName : !Sub "${Stage}-processing"
VisibilityTimeout : 360
Outputs :
ApiEndpoint :
Value : !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod"
```
```bash
# SAM CLI commands
sam build
sam local invoke ApiFunction --event events/get-items.json
sam local start-api --port 3000
sam deploy --guided
sam logs --name ApiFunction --stack-name my-stack --tail
```
## Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| Function times out | Timeout too low or downstream slow | Increase timeout; check VPC/NAT config |
| Out of memory | Memory limit too small | Increase `--memory-size` ; profile with CloudWatch Insights |
| Permission denied on AWS API | Execution role missing policy | Attach required policy to the execution role |
| Cold starts > 5s | Large package or VPC overhead | Use layers, arm64, provisioned concurrency; remove VPC if not needed |
| SQS messages reprocessed | Visibility timeout < function timeout | Set queue visibility timeout to 6x function timeout |
| Event source mapping disabled | Too many consecutive errors | Fix the function error; re-enable the mapping |
| Layer not found | Wrong region or deleted version | Verify layer ARN region matches function region |
| Canary deployment not shifting | Alias routing config wrong | Verify version numbers in routing config |
| Cannot invoke function URL | Missing resource-based policy | Add `lambda:InvokeFunctionUrl` permission |
2026-01-27 17:35:45 -05:00
## Related Skills
2026-03-24 18:02:50 -04:00
- [aws-iam ](../aws-iam/ ) - Execution roles and permissions
- [terraform-aws ](../terraform-aws/ ) - IaC deployment for Lambda
- [aws-s3 ](../aws-s3/ ) - S3 event triggers
- [aws-vpc ](../aws-vpc/ ) - VPC configuration for Lambda
- [aws-cost-optimization ](../aws-cost-optimization/ ) - Optimizing Lambda spend