aws-serverless
Skill2 starsChanged 42 days agoMITView on GitHub
Specialized skill for building production-ready serverless
- Reads credentials
- Installs packages
11 other projects use a version of this, 4 of them edited.
Adopted by
Most recently taken up by
- delorenj/skillstheir own version, first seen Nov 7, 2026
- JuankCadavid/akili-specsedited, first seen Nov 2, 2026
- thiago-shopper/claude-skillstheir own version, first seen Nov 1, 2026
- opensite-ai/opensite-skillstheir own version, first seen Nov 1, 2026
- xfstudio/skillsedited, first seen Oct 13, 2026
- nimadorostkar/Claude-Skills-collectiontheir own version, first seen Oct 13, 2026
Other versions11 projects use a version of this.
Word for word · 0
None found.
Edited · 4
- tranhieutt/software_development_department★ 7126% same
- JuankCadavid/akili-specs★ 1079% same
- xfstudio/skills★ 981% same
- ai4brands-design/claude-skills★ 281% same
Wrote their own version · 7
- aws/agent-toolkit-for-aws★ 3.4ksame name
- nimadorostkar/Claude-Skills-collection★ 33same name
- delorenj/skills★ 17same name
- opensite-ai/opensite-skills★ 15same name
- a-pavithraa/aws-serverless-skill★ 8same name
- richardnroman/Synthetic-Data-Exchange-Licensing-Platform★ 0same name
- thiago-shopper/claude-skills★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository191 other files it gives its agents.
- AGENTS.mdAGENTS.md
- docs/agents.mdAGENTS.md
- skills/postgres-best-practices/AGENTS.mdAGENTS.md
- skills/react-best-practices/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- accessibility-compliance-accessibility-auditSkill
- acquire-codebase-knowledgeSkill
- advanced-evaluationSkill
- agent-evaluationSkill
- alexSkill
- ariaSkill
- depSkill
- lunaSkill
- masonSkill
- maxSkill
- quinnSkill
- rexSkill
- agent-squadSkill
- ai-agent-developmentSkill
- ai-agents-architectSkill
- ai-engineering-toolkitSkill
- api-and-interface-designSkill
- api-design-principlesSkill
- api-documentation-generatorSkill
- api-documentationSkill
- api-documenterSkill
- api-endpoint-builderSkill
- api-fuzzing-bug-bountySkill
- api-patternsSkill
- api-security-testingSkill
- api-testing-observability-api-mockSkill
- application-performance-performance-optimizationSkill
- architecture-decision-recordsSkill
- architecture-patternsSkill
- async-python-patternsSkill
- attack-tree-constructionSkill
- autonomous-agent-patternsSkill
- aws-cost-optimizerSkill
- awt-e2e-testingSkill
- azure-functionsSkill
- backend-architectSkill
- backend-dev-guidelinesSkill
- backend-security-coderSkill
- brainstormingSkill
- breakdown-feature-implementationSkill
- breakdown-feature-prdSkill
- broken-authenticationSkill
- browser-testing-with-devtoolsSkill
- ci-cd-and-automationSkill
- clean-codeSkill
- cloud-architectSkill
- cloud-devopsSkill
- cloudformation-best-practicesSkill
- code-refactoring-refactor-cleanSkill
- code-refactoring-tech-debtSkill
- code-review-and-qualitySkill
- code-simplificationSkill
- comprehensive-review-full-reviewSkill
- comprehensive-review-pr-enhanceSkill
- container-security-hardeningSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
18 rules. 0 are common, 18 are distinctive, and 0 are very specific to this project.
0
Common
Most of the 5 edited versions we read keep these.
18
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Use SnapStart for Java/.NET functions
- Distinctive: line 17
Prefer HTTP API over REST API for simple use cases
- Distinctive: line 19
Keep deployment packages small
- Distinctive: line 20
Use environment variables for configuration
- Distinctive: line 152
Always return proper API Gateway response format
- Distinctive: line 390
Use ReportBatchItemFailures for partial batch failure
- Distinctive: line 391
Always configure a DLQ for poison messages
- Distinctive: line 804
Default Lambda timeout is only 3 seconds.
- Distinctive: line 807
Default timeout too short for workload
- Distinctive: line 878
When Lambda exceeds memory allocation, AWS forcibly terminates the runtime.
- Distinctive: line 1011
Don't attach Lambda to VPC unless you need:
- Distinctive: line 1261
Avoid wildcard permissions in Lambda IAM roles
- Distinctive: line 1285
Default 128MB may be too low for many workloads
- Distinctive: line 1309
Import specific clients from AWS SDK v3 for smaller packages
- Distinctive: line 1333
Use this skill when the request clearly matches the capabilities and patterns described above.
- Distinctive: line 1336
Use this skill only when the task clearly matches the scope described above.
- Distinctive: line 1337
Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Distinctive: line 1338
Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
AWS Serverless
Specialized skill for building production-ready serverless applications on AWS. Covers Lambda functions, API Gateway, DynamoDB, SQS/SNS event-driven patterns, SAM/CDK deployment, and cold start optimization.
Principles
- Right-size memory and timeout (measure before optimizing)
- Minimize cold starts for latency-sensitive workloads
- Use SnapStart for Java/.NET functions
- Prefer HTTP API over REST API for simple use cases
- Design for failure with DLQs and retries
- Keep deployment packages small
- Use environment variables for configuration
- Implement structured logging with correlation IDs
Patterns
Lambda Handler Pattern
Proper Lambda function structure with error handling
When to use: Any Lambda function implementation,API handlers, event processors, scheduled tasks
// Node.js Lambda Handler
// handler.js
// Initialize outside handler (reused across invocations)
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
// Handler function
exports.handler = async (event, context) => {
// Optional: Don't wait for event loop to clear (Node.js)
context.callbackWaitsForEmptyEventLoop = false;
try {
// Parse input based on event source
const body = typeof event.body === 'string'
? JSON.parse(event.body)
: event.body;
// Business logic
const result = await processRequest(body);
// Return API Gateway compatible response
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(result)
};
} catch (error) {
console.error('Error:', JSON.stringify({
error: error.message,
stack: error.stack,
requestId: context.awsRequestId
}));
return {
statusCode: error.statusCode || 500,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
error: error.message || 'Internal server error'
})
};
}
};
async function processRequest(data) {
// Your business logic here
const result = await docClient.send(new GetCommand({
TableName: process.env.TABLE_NAME,
Key: { id: data.id }
}));
return result.Item;
}# Python Lambda Handler
# handler.py
import json
import os
import logging
import boto3
from botocore.exceptions import ClientError
# Initialize outside handler (reused across invocations)
logger = logging.getLogger()
logger.setLevel(logging.INFO)
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])
def handler(event, context):
try:
# Parse input
body = json.loads(event.get('body', '{}')) if isinstance(event.get('body'), str) else event.get('body', {})
# Business logic
result = process_request(body)
return {
'statusCode': 200,
'headers': {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps(result)
}
except ClientError as e:
logger.error(f"DynamoDB error: {e.response['Error']['Message']}")
return error_response(500, 'Database error')
except json.JSONDecodeError:
return error_response(400, 'Invalid JSON')
except Exception as e:
logger.error(f"Unexpected error: {str(e)}", exc_info=True)
return error_response(500, 'Internal server error')
def process_request(data):
response = table.get_item(Key={'id': data['id']})
return response.get('Item')
def error_response(status_code, message):
return {
'statusCode': status_code,
'headers': {'Content-Type': 'application/json'},
'body': json.dumps({'error': message})
}Best_practices
- Initialize clients outside handler (reused across warm invocations)
- Always return proper API Gateway response format
- Log with structured JSON for CloudWatch Insights
- Include request ID in error logs for tracing
API Gateway Integration Pattern
REST API and HTTP API integration with Lambda
When to use: Building REST APIs backed by Lambda,Need HTTP endpoints for functions
# template.yaml (SAM)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: nodejs20.x
Timeout: 30
MemorySize: 256
Environment:
Variables:
TABLE_NAME: !Ref ItemsTable
Resources:
# HTTP API (recommended for simple use cases)
HttpApi:
Type: AWS::Serverless::HttpApi
Properties:
StageName: prod
CorsConfiguration:
AllowOrigins:
- "*"
AllowMethods:
- GET
- POST
- DELETE
AllowHeaders:
- "*"
# Lambda Functions
GetItemFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/get.handler
Events:
GetItem:
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Path: /items/{id}
Method: GET
Policies:
- DynamoDBReadPolicy:
TableName: !Ref ItemsTable
CreateItemFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/create.handler
Events:
CreateItem:
Type: HttpApi
Properties:
ApiId: !Ref HttpApi
Path: /items
Method: POST
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref ItemsTable
# DynamoDB Table
ItemsTable:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
Outputs:
ApiUrl:
Value: !Sub "https://${HttpApi}.execute-api.${AWS::Region}.amazonaws.com/prod"// src/handlers/get.js
const { getItem } = require('../lib/dynamodb');
exports.handler = async (event) => {
const id = event.pathParameters?.id;
if (!id) {
return {
statusCode: 400,
body: JSON.stringify({ error: 'Missing id parameter' })
};
}
const item = await getItem(id);
if (!item) {
return {
statusCode: 404,
body: JSON.stringify({ error: 'Item not found' })
};
}
return {
statusCode: 200,
body: JSON.stringify(item)
};
};Structure
project/ ├── template.yaml # SAM template ├── src/ │ ├── handlers/ │ │ ├── get.js │ │ ├── create.js │ │ └── delete.js │ └── lib/ │ └── dynamodb.js └── events/ └── event.json # Test events
Api_comparison
- Http_api:
- Lower latency (~10ms)
- Lower cost (50-70% cheaper)
- Simpler, fewer features
- Best for: Most REST APIs
- Rest_api:
- More features (caching, request validation, WAF)
- Usage plans and API keys
- Request/response transformation
- Best for: Complex APIs, enterprise features
Event-Driven SQS Pattern
Lambda triggered by SQS for reliable async processing
When to use: Decoupled, asynchronous processing,Need retry logic and DLQ,Processing messages in batches
# template.yaml
Resources:
ProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/processor.handler
Events:
SQSEvent:
Type: SQS
Properties:
Queue: !GetAtt ProcessingQueue.Arn
BatchSize: 10
FunctionResponseTypes:
- ReportBatchItemFailures # Partial batch failure handling
ProcessingQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 180 # 6x Lambda timeout
RedrivePolicy:
deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
maxReceiveCount: 3
DeadLetterQueue:
Type: AWS::SQS::Queue
Properties:
MessageRetentionPeriod: 1209600 # 14 days// src/handlers/processor.js
exports.handler = async (event) => {
const batchItemFailures = [];
for (const record of event.Records) {
try {
const body = JSON.parse(record.body);
await processMessage(body);
} catch (error) {
console.error(`Failed to process message ${record.messageId}:`, error);
// Report this item as failed (will be retried)
batchItemFailures.push({
itemIdentifier: record.messageId
});
}
}
// Return failed items for retry
return { batchItemFailures };
};
async function processMessage(message) {
// Your processing logic
console.log('Processing:', message);
// Simulate work
await saveToDatabase(message);
}# Python version
import json
import logging
logger = logging.getLogger()
def handler(event, context):
batch_item_failures = []
for record in event['Records']:
try:
body = json.loads(record['body'])
process_message(body)
except Exception as e:
logger.error(f"Failed to process {record['messageId']}: {e}")
batch_item_failures.append({
'itemIdentifier': record['messageId']
})
return {'batchItemFailures': batch_item_failures}Best_practices
- Set VisibilityTimeout to 6x Lambda timeout
- Use ReportBatchItemFailures for partial batch failure
- Always configure a DLQ for poison messages
- Process messages idempotently
DynamoDB Streams Pattern
React to DynamoDB table changes with Lambda
When to use: Real-time reactions to data changes,Cross-region replication,Audit logging, notifications
# template.yaml
Resources:
ItemsTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: items
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
BillingMode: PAY_PER_REQUEST
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
StreamProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/stream.handler
Events:
Stream:
Type: DynamoDB
Properties:
Stream: !GetAtt ItemsTable.StreamArn
StartingPosition: TRIM_HORIZON
BatchSize: 100
MaximumRetryAttempts: 3
DestinationConfig:
OnFailure:
Destination: !GetAtt StreamDLQ.Arn
StreamDLQ:
Type: AWS::SQS::Queue// src/handlers/stream.js
exports.handler = async (event) => {
for (const record of event.Records) {
const eventName = record.eventName; // INSERT, MODIFY, REMOVE
// Unmarshall DynamoDB format to plain JS objects
const newImage = record.dynamodb.NewImage
? unmarshall(record.dynamodb.NewImage)
: null;
const oldImage = record.dynamodb.OldImage
? unmarshall(record.dynamodb.OldImage)
: null;
console.log(`${eventName}: `, { newImage, oldImage });
switch (eventName) {
case 'INSERT':
await handleInsert(newImage);
break;
case 'MODIFY':
await handleModify(oldImage, newImage);
break;
case 'REMOVE':
await handleRemove(oldImage);
break;
}
}
};
// Use AWS SDK v3 unmarshall
const { unmarshall } = require('@aws-sdk/util-dynamodb');Stream_view_types
- KEYS_ONLY: Only key attributes
- NEW_IMAGE: After modification
- OLD_IMAGE: Before modification
- NEW_AND_OLD_IMAGES: Both before and after
Cold Start Optimization Pattern
Minimize Lambda cold start latency
When to use: Latency-sensitive applications,User-facing APIs,High-traffic functions
1. Optimize Package Size
// Use modular AWS SDK v3 imports
// GOOD - only imports what you need
const { DynamoDBClient } = require('@aws-sdk/client-dynamodb');
const { DynamoDBDocumentClient, GetCommand } = require('@aws-sdk/lib-dynamodb');
// BAD - imports entire SDK
const AWS = require('aws-sdk'); // Don't do this!2. Use SnapStart (Java/.NET)
# template.yaml
Resources:
JavaFunction:
Type: AWS::Serverless::Function
Properties:
Handler: com.example.Handler::handleRequest
Runtime: java21
SnapStart:
ApplyOn: PublishedVersions # Enable SnapStart
AutoPublishAlias: live3. Right-size Memory
# More memory = more CPU = faster init
Resources:
FastFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1024 # 1GB gets full vCPU
Timeout: 304. Provisioned Concurrency (when needed)
Resources:
CriticalFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/critical.handler
AutoPublishAlias: live
ProvisionedConcurrency:
Type: AWS::Lambda::ProvisionedConcurrencyConfig
Properties:
FunctionName: !Ref CriticalFunction
Qualifier: live
ProvisionedConcurrentExecutions: 55. Keep Init Light
# GOOD - Lazy initialization
_table = None
def get_table():
global _table
if _table is None:
dynamodb = boto3.resource('dynamodb')
_table = dynamodb.Table(os.environ['TABLE_NAME'])
return _table
def handler(event, context):
table = get_table() # Only initializes on first use
# ...Optimization_priority
- 1: Reduce package size (biggest impact)
- 2: Use SnapStart for Java/.NET
- 3: Increase memory for faster init
- 4: Delay heavy imports
- 5: Provisioned concurrency (last resort)
SAM Local Development Pattern
Local testing and debugging with SAM CLI
When to use: Local development and testing,Debugging Lambda functions,Testing API Gateway locally
# Install SAM CLI
pip install aws-sam-cli
# Initialize new project
sam init --runtime nodejs20.x --name my-api
# Build the project
sam build
# Run locally
sam local start-api
# Invoke single function
sam local invoke GetItemFunction --event events/get.json
# Local debugging (Node.js with VS Code)
sam local invoke --debug-port 5858 GetItemFunction
# Deploy
sam deploy --guided// events/get.json (test event)
{
"pathParameters": {
"id": "123"
},
"httpMethod": "GET",
"path": "/items/123"
}// .vscode/launch.json (for debugging)
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to SAM CLI",
"type": "node",
"request": "attach",
"address": "localhost",
"port": 5858,
"localRoot": "${workspaceRoot}/src",
"remoteRoot": "/var/task/src",
"protocol": "inspector"
}
]
}Commands
- Sam_build: Build Lambda deployment packages
- Sam_local_start_api: Start local API Gateway
- Sam_local_invoke: Invoke single function
- Sam_deploy: Deploy to AWS
- Sam_logs: Tail CloudWatch logs
CDK Serverless Pattern
Infrastructure as code with AWS CDK
When to use: Complex infrastructure beyond Lambda,Prefer programming languages over YAML,Need reusable constructs
// lib/api-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
export class ApiStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// DynamoDB Table
const table = new dynamodb.Table(this, 'ItemsTable', {
partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.DESTROY, // For dev only
});
// Lambda Function
const getItemFn = new lambda.Function(this, 'GetItemFunction', {
runtime: lambda.Runtime.NODEJS_20_X,
handler: 'get.handler',
code: lambda.Code.fromAsset('src/handlers'),
environment: {
TABLE_NAME: table.tableName,
},
memorySize: 256,
timeout: cdk.Duration.seconds(30),
});
// Grant permissions
table.grantReadData(getItemFn);
// API Gateway
const api = new apigateway.RestApi(this, 'ItemsApi', {
restApiName: 'Items Service',
defaultCorsPreflightOptions: {
allowOrigins: apigateway.Cors.ALL_ORIGINS,
allowMethods: apigateway.Cors.ALL_METHODS,
},
});
const items = api.root.addResource('items');
const item = items.addResource('{id}');
item.addMethod('GET', new apigateway.LambdaIntegration(getItemFn));
// Output API URL
new cdk.CfnOutput(this, 'ApiUrl', {
value: api.url,
});
}
}# CDK commands
npm install -g aws-cdk
cdk init app --language typescript
cdk synth # Generate CloudFormation
cdk diff # Show changes
cdk deploy # Deploy to AWSSharp Edges
Cold Start INIT Phase Now Billed (Aug 2025)
Severity: HIGH
Situation: Running Lambda functions in production
Symptoms: Unexplained increase in Lambda costs (10-50% higher). Bill includes charges for function initialization. Functions with heavy startup logic cost more than expected.
Why this breaks: As of August 1, 2025, AWS bills the INIT phase the same way it bills invocation duration. Previously, cold start initialization wasn't billed for the full duration.
This affects functions with:
- Heavy dependency loading (large packages)
- Slow initialization code
- Frequent cold starts (low traffic or poor concurrency)
Cold starts now directly impact your bill, not just latency.
Recommended fix:
Measure your INIT phase
# Check CloudWatch Logs for INIT_REPORT
# Look for Init Duration in milliseconds
# Example log line:
# INIT_REPORT Init Duration: 423.45 msReduce INIT duration
// 1. Minimize package size
// Use tree shaking, exclude dev dependencies
// npm prune --production
// 2. Lazy load heavy dependencies
let heavyLib = null;
function getHeavyLib() {
if (!heavyLib) {
heavyLib = require('heavy-library');
}
return heavyLib;
}
// 3. Use AWS SDK v3 modular imports
const { S3Client } = require('@aws-sdk/client-s3');
// NOT: const AWS = require('aws-sdk');Use SnapStart for Java/.NET
Resources:
JavaFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: java21
SnapStart:
ApplyOn: PublishedVersionsMonitor cold start frequency
// Track cold starts with custom metric
let isColdStart = true;
exports.handler = async (event) => {
if (isColdStart) {
console.log('COLD_START');
// CloudWatch custom metric here
isColdStart = false;
}
// ...
};Lambda Timeout Misconfiguration
Severity: HIGH
Situation: Running Lambda functions, especially with external calls
Symptoms: Function times out unexpectedly. "Task timed out after X seconds" in logs. Partial processing with no response. Silent failures with no error caught.
Why this breaks: Default Lambda timeout is only 3 seconds. Maximum is 15 minutes.
Common timeout causes:
- Default timeout too short for workload
- Downstream service taking longer than expected
- Network issues in VPC
- Infinite loops or blocking operations
- S3 downloads larger than expected
Lambda terminates at timeout without graceful shutdown.
Recommended fix:
Set appropriate timeout
# template.yaml
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Timeout: 30 # Seconds (max 900)
# Set to expected duration + bufferImplement timeout awareness
exports.handler = async (event, context) => {
// Get remaining time
const remainingTime = context.getRemainingTimeInMillis();
// If running low on time, fail gracefully
if (remainingTime < 5000) {
console.warn('Running low on time, aborting');
throw new Error('Insufficient time remaining');
}
// For long operations, check periodically
for (const item of items) {
if (context.getRemainingTimeInMillis() < 10000) {
// Save progress and exit gracefully
await saveProgress(processedItems);
throw new Error('Timeout approaching, saved progress');
}
await processItem(item);
}
};Set downstream timeouts
const axios = require('axios');
// Always set timeouts on HTTP calls
const response = await axios.get('https://api.example.com/data', {
timeout: 5000 // 5 seconds
});Out of Memory (OOM) Crash
Severity: HIGH
Situation: Lambda function processing data
Symptoms: Function stops abruptly without error. CloudWatch logs appear truncated. "Max Memory Used" hits configured limit. Inconsistent behavior under load.
Why this breaks: When Lambda exceeds memory allocation, AWS forcibly terminates the runtime. This happens without raising a catchable exception.
Common causes:
- Processing large files in memory
- Memory leaks across invocations
- Buffering entire response bodies
- Heavy libraries consuming too much memory
Recommended fix:
Increase memory allocation
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1024 # MB (128-10240)
# More memory = more CPU tooStream large data
// BAD - loads entire file into memory
const data = await s3.getObject(params).promise();
const content = data.Body.toString();
// GOOD - stream processing
const { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');
const s3 = new S3Client({});
const response = await s3.send(new GetObjectCommand(params));
const stream = response.Body;
// Process stream in chunks
for await (const chunk of stream) {
await processChunk(chunk);
}Monitor memory usage
exports.handler = async (event, context) => {
const used = process.memoryUsage();
console.log('Memory:', {
heapUsed: Math.round(used.heapUsed / 1024 / 1024) + 'MB',
heapTotal: Math.round(used.heapTotal / 1024 / 1024) + 'MB'
});
// ...
};Use Lambda Power Tuning
# Find optimal memory setting
# https://github.com/alexcasalboni/aws-lambda-power-tuningVPC-Attached Lambda Cold Start Delay
Severity: MEDIUM
Situation: Lambda functions in VPC accessing private resources
Symptoms: Extremely slow cold starts (was 10+ seconds, now ~100ms). Timeouts on first invocation after idle period. Functions work in VPC but slow compared to non-VPC.
Why this breaks: Lambda functions in VPC need Elastic Network Interfaces (ENIs). AWS improved this significantly with Hyperplane ENIs, but:
- First cold start in VPC still has overhead
- NAT Gateway issues can cause timeouts
- Security group misconfig blocks traffic
- DNS resolution can be slow
Recommended fix:
Verify VPC configuration
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2 # Multiple AZs
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Lambda SG
VpcId: !Ref VPC
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0 # Allow HTTPS outboundUse VPC endpoints for AWS services
# Avoid NAT Gateway for AWS service calls
DynamoDBEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.dynamodb
VpcId: !Ref VPC
RouteTableIds:
- !Ref PrivateRouteTable
VpcEndpointType: Gateway
S3Endpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcId: !Ref VPC
VpcEndpointType: GatewayOnly use VPC when necessary
Don't attach Lambda to VPC unless you need:
- Access to RDS/ElastiCache in VPC
- Access to private EC2 instances
- Compliance requirements
Most AWS services can be accessed without VPC.
Node.js Event Loop Not Cleared
Severity: MEDIUM
Situation: Node.js Lambda function with callbacks or timers
Symptoms: Function takes full timeout duration to return. "Task timed out" even though logic completed. Extra billing for idle time.
Why this breaks: By default, Lambda waits for the Node.js event loop to be empty before returning. If you have:
- Unresolved setTimeout/setInterval
- Dangling database connections
- Pending callbacks
Lambda waits until timeout, even if your response was ready.
Recommended fix:
Tell Lambda not to wait for event loop
exports.handler = async (event, context) => {
// Don't wait for event loop to clear
context.callbackWaitsForEmptyEventLoop = false;
// Your code here
const result = await processRequest(event);
return {
statusCode: 200,
body: JSON.stringify(result)
};
};Close connections properly
// For database connections, use connection pooling
// or close connections explicitly
const mysql = require('mysql2/promise');
exports.handler = async (event, context) => {
context.callbackWaitsForEmptyEventLoop = false;
const connection = await mysql.createConnection({...});
try {
const [rows] = await connection.query('SELECT * FROM users');
return { statusCode: 200, body: JSON.stringify(rows) };
} finally {
await connection.end(); // Always close
}
};API Gateway Payload Size Limits
Severity: MEDIUM
Situation: Returning large responses or receiving large requests
Symptoms: "413 Request Entity Too Large" error "Execution failed due to configuration error: Malformed Lambda proxy response" Response truncated or failed
Why this breaks: API Gateway has hard payload limits:
- REST API: 10 MB request/response
- HTTP API: 10 MB request/response
- Lambda itself: 6 MB sync response, 256 KB async
Exceeding these causes failures that may not be obvious.
Recommended fix:
For large file uploads
// Use presigned S3 URLs instead of passing through API Gateway
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');
exports.handler = async (event) => {
const s3 = new S3Client({});
const command = new PutObjectCommand({
Bucket: process.env.BUCKET_NAME,
Key: `uploads/${Date.now()}.file`
});
const uploadUrl = await getSignedUrl(s3, command, { expiresIn: 300 });
return {
statusCode: 200,
body: JSON.stringify({ uploadUrl })
};
};For large responses
// Store in S3, return presigned download URL
exports.handler = async (event) => {
const largeData = await generateLargeReport();
await s3.send(new PutObjectCommand({
Bucket: process.env.BUCKET_NAME,
Key: `reports/${reportId}.json`,
Body: JSON.stringify(largeData)
}));
const downloadUrl = await getSignedUrl(s3,
new GetObjectCommand({
Bucket: process.env.BUCKET_NAME,
Key: `reports/${reportId}.json`
}),
{ expiresIn: 3600 }
);
return {
statusCode: 200,
body: JSON.stringify({ downloadUrl })
};
};Infinite Loop or Recursive Invocation
Severity: HIGH
Situation: Lambda triggered by events
Symptoms: Runaway costs. Thousands of invocations in minutes. CloudWatch logs show repeated invocations. Lambda writing to source bucket/table that triggers it.
Why this breaks: Lambda can accidentally trigger itself:
- S3 trigger writes back to same bucket
- DynamoDB trigger updates same table
- SNS publishes to topic that triggers it
- Step Functions with wrong error handling
Recommended fix:
Use different buckets/prefixes
# S3 trigger with prefix filter
Events:
S3Event:
Type: S3
Properties:
Bucket: !Ref InputBucket
Events: s3:ObjectCreated:*
Filter:
S3Key:
Rules:
- Name: prefix
Value: uploads/ # Only trigger on uploads/
# Output to different bucket or prefix
# OutputBucket or processed/ prefixAdd idempotency checks
exports.handler = async (event) => {
for (const record of event.Records) {
const key = record.s3.object.key;
// Skip if this is a processed file
if (key.startsWith('processed/')) {
console.log('Skipping already processed file:', key);
continue;
}
// Process and write to different location
await processFile(key);
await writeToS3(`processed/${key}`, result);
}
};Set reserved concurrency as circuit breaker
Resources:
RiskyFunction:
Type: AWS::Serverless::Function
Properties:
ReservedConcurrentExecutions: 10 # Max 10 parallel
# Limits blast radius of runaway invocationsMonitor with CloudWatch alarms
InvocationAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
MetricName: Invocations
Namespace: AWS/Lambda
Statistic: Sum
Period: 60
EvaluationPeriods: 1
Threshold: 1000 # Alert if >1000 invocations/min
ComparisonOperator: GreaterThanThresholdValidation Checks
Hardcoded AWS Credentials
Severity: ERROR
AWS credentials must never be hardcoded
Message: Hardcoded AWS access key detected. Use IAM roles or environment variables.
AWS Secret Key in Source Code
Severity: ERROR
Secret keys should use Secrets Manager or environment variables
Message: Hardcoded AWS secret key. Use IAM roles or Secrets Manager.
Overly Permissive IAM Policy
Severity: WARNING
Avoid wildcard permissions in Lambda IAM roles
Message: Overly permissive IAM policy. Use least privilege principle.
Lambda Handler Without Error Handling
Severity: WARNING
Lambda handlers should have try/catch for graceful errors
Message: Lambda handler without error handling. Add try/catch.
Missing callbackWaitsForEmptyEventLoop
Severity: INFO
Node.js handlers should set callbackWaitsForEmptyEventLoop
Message: Consider setting context.callbackWaitsForEmptyEventLoop = false
Default Memory Configuration
Severity: INFO
Default 128MB may be too low for many workloads
Message: Using default 128MB memory. Consider increasing for better performance.
Low Timeout Configuration
Severity: WARNING
Very low timeout may cause unexpected failures
Message: Timeout of 1-3 seconds may be too low. Increase if making external calls.
No Dead Letter Queue Configuration
Severity: WARNING
Async functions should have DLQ for failed invocations
Message: No DLQ configured. Add for async invocations.
Importing Full AWS SDK v2
Severity: WARNING
Import specific clients from AWS SDK v3 for smaller packages
Message: Importing full AWS SDK. Use modular SDK v3 imports for smaller packages.
Hardcoded DynamoDB Table Name
Severity: WARNING
Table names should come from environment variables
Message: Hardcoded table name. Use environment variable for portability.
Collaboration
Delegation Triggers
- user needs GCP serverless -> gcp-cloud-run (Cloud Run for containers, Cloud Functions for events)
- user needs Azure serverless -> azure-functions (Azure Functions, Logic Apps)
- user needs database design -> postgres-wizard (RDS design, or use DynamoDB patterns)
- user needs authentication -> auth-specialist (Cognito, API Gateway authorizers)
- user needs complex workflows -> workflow-automation (Step Functions, EventBridge)
- user needs AI integration -> llm-architect (Lambda calling Bedrock or external LLMs)
When to Use
Use this skill when the request clearly matches the capabilities and patterns described above.
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

