Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/davila7-aws-serverless/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-12 | ✓→✗ | ▼ Worse | 108% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 66% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 118% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 136% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 69% | 0% |
Proper Lambda function structure with error handling
When to use: 'Any Lambda function implementation', 'API handlers, event processors, scheduled tasks']
python
// 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; }
import json import os import logging import boto3 from botocore.exceptions import ClientError
logger = logging.getLogger() logger.setLevel(logging.INFO)
dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ'TABLE_NAME'])
def handler(event, context): try: # Parse i
### 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']
yaml# 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"
javascript// 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 =
Lambda triggered by SQS for reliable async processing
When to use: 'Decoupled, asynchronous processing', 'Need retry logic and DLQ', 'Processing messages in batches']
python
Resources: ProcessorFunction: Type: AWS::Serverless::Function Properties: Handler: src/handlers/processor.handler Events: SQSEvent: Type: SQS Properties: Queue: !GetAtt ProcessingQueue.Arn BatchSize: 10 FunctionResponseTypes:
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); }
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_ite
## Anti-Patterns
### ❌ Monolithic Lambda
**Why bad**: Large deployment packages cause slow cold starts.
Hard to scale individual operations.
Updates affect entire system.
### ❌ Large Dependencies
**Why bad**: Increases deployment package size.
Slows down cold starts significantly.
Most of SDK/library may be unused.
### ❌ Synchronous Calls in VPC
**Why bad**: VPC-attached Lambdas have ENI setup overhead.
Blocking DNS lookups or connections worsen cold starts.
## ⚠️ Sharp Edges
| Issue | Severity | Solution |
|-------|----------|----------|
| Issue | high | ## Measure your INIT phase |
| Issue | high | ## Set appropriate timeout |
| Issue | high | ## Increase memory allocation |
| Issue | medium | ## Verify VPC configuration |
| Issue | medium | ## Tell Lambda not to wait for event loop |
| Issue | medium | ## For large file uploads |
| Issue | high | ## Use different buckets/prefixes || Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 11,621 | 9,152 | -21% | 1 | 1 | 0% | 2,552 | 4,125 | +62% | 0 | 0 | — |
case-02 | pass→pass | 11,763 | 9,778 | -17% | 1 | 1 | 0% | 2,424 | 4,023 | +66% | 0 | 0 | — |
case-03 | pass→pass | 7,667 | 6,744 | -12% | 1 | 1 | 0% | 1,615 | 3,525 | +118% | 0 | 0 | — |
case-04 | pass→pass | 5,761 | 4,005 | -30% | 1 | 1 | 0% | 1,188 | 2,806 | +136% | 0 | 0 | — |
case-05 | pass→pass | 9,434 | 4,869 | -48% | 1 | 1 | 0% | 1,828 | 3,094 | +69% | 0 | 0 | — |
case-06 | pass→pass | 7,247 | 7,231 | -0% | 1 | 1 | 0% | 1,462 | 3,574 | +144% | 0 | 0 | — |
case-07 | pass→pass | 8,473 | 5,895 | -30% | 1 | 1 | 0% | 1,865 | 3,125 | +68% | 0 | 0 | — |
case-08 | pass→pass | 4,221 | 4,195 | -1% | 1 | 1 | 0% | 889 | 2,909 | +227% | 0 | 0 | — |
case-09 | pass→pass | 7,560 | 3,818 | -49% | 1 | 1 | 0% | 1,393 | 2,780 | +100% | 0 | 0 | — |
case-10 | pass→pass | 14,432 | 12,130 | -16% | 1 | 1 | 0% | 3,322 | 4,786 | +44% | 0 | 0 | — |
case-11 | fail→fail | 14,550 | 10,481 | -28% | 1 | 1 | 0% | 2,428 | 3,808 | +57% | 0 | 0 | — |
case-12 | pass→fail | 10,434 | 9,611 | -8% | 1 | 1 | 0% | 1,790 | 3,726 | +108% | 0 | 0 | — |
case-13 | pass→pass | 13,252 | 10,257 | -23% | 1 | 1 | 0% | 2,051 | 3,809 | +86% | 0 | 0 | — |
case-14 | pass→pass | 5,519 | 3,726 | -32% | 1 | 1 | 0% | 1,102 | 2,700 | +145% | 0 | 0 | — |
case-15 | pass→pass | 4,921 | 4,226 | -14% | 1 | 1 | 0% | 899 | 2,859 | +218% | 0 | 0 | — |
case-16 | pass→pass | 5,973 | 4,173 | -30% | 1 | 1 | 0% | 1,205 | 2,859 | +137% | 0 | 0 | — |
case-17 | pass→pass | 11,015 | 9,014 | -18% | 1 | 1 | 0% | 2,466 | 3,986 | +62% | 0 | 0 | — |
case-18 | pass→pass | 3,516 | 3,829 | +9% | 1 | 1 | 0% | 697 | 2,718 | +290% | 0 | 0 | — |
case-19 | pass→pass | 4,002 | 3,407 | -15% | 1 | 1 | 0% | 792 | 2,686 | +239% | 0 | 0 | — |
case-20 | pass→pass | 5,018 | 7,002 | +40% | 1 | 1 | 0% | 957 | 3,468 | +262% | 0 | 0 | — |
case-21 | pass→pass | 6,558 | 5,119 | -22% | 1 | 1 | 0% | 1,255 | 3,073 | +145% | 0 | 0 | — |
case-22 | pass→pass | 8,560 | 7,880 | -8% | 1 | 1 | 0% | 1,592 | 3,449 | +117% | 0 | 0 | — |
case-23 | pass→pass | 7,544 | 4,867 | -35% | 1 | 1 | 0% | 1,482 | 3,003 | +103% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of -4 percentage points is the difference between those two pass rates over the 23 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Other measured skills in the registry, with their headline benchmark lift.