Claude-skill-registry aws-lambda
Build serverless applications with AWS Lambda and TypeScript. Covers handler patterns, API Gateway integration, DynamoDB operations, SQS/S3/DynamoDB Streams event sources, SAM templates, and CDK infrastructure. Use for serverless APIs, event-driven architectures, and AWS backend development.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/aws-lambda" ~/.claude/skills/majiayu000-claude-skill-registry-aws-lambda && rm -rf "$T"
manifest:
skills/data/aws-lambda/SKILL.mdsource content
AWS Lambda Skill
Expert guidance for AWS Lambda with TypeScript, API Gateway, DynamoDB, and serverless patterns.
Triggers
Use this skill when you see:
- aws lambda, lambda function, serverless aws
- api gateway, sam template, cdk lambda
- dynamodb streams, sqs handler, s3 trigger
- lambda handler, cold start, provisioned concurrency
Instructions
Lambda Handler Patterns
Basic Handler with TypeScript
import type { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; export const handler = async ( event: APIGatewayProxyEvent, context: Context ): Promise<APIGatewayProxyResult> => { try { const body = JSON.parse(event.body ?? '{}'); // Your logic here const result = await processRequest(body); return { statusCode: 200, headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', }, body: JSON.stringify(result), }; } catch (error) { console.error('Error:', error); return { statusCode: 500, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ error: 'Internal Server Error' }), }; } };
Middleware Pattern with Middy
import middy from '@middy/core'; import jsonBodyParser from '@middy/http-json-body-parser'; import httpErrorHandler from '@middy/http-error-handler'; import cors from '@middy/http-cors'; import validator from '@middy/validator'; import { transpileSchema } from '@middy/validator/transpile'; const inputSchema = { type: 'object', properties: { body: { type: 'object', properties: { email: { type: 'string', format: 'email' }, name: { type: 'string', minLength: 1 }, }, required: ['email', 'name'], }, }, }; const baseHandler = async (event: APIGatewayProxyEvent) => { const { email, name } = event.body as { email: string; name: string }; const user = await createUser({ email, name }); return { statusCode: 201, body: JSON.stringify(user), }; }; export const handler = middy(baseHandler) .use(jsonBodyParser()) .use(validator({ eventSchema: transpileSchema(inputSchema) })) .use(httpErrorHandler()) .use(cors());
Event Source Handlers
SQS Handler
import type { SQSEvent, SQSHandler } from 'aws-lambda'; export const sqsHandler: SQSHandler = async (event: SQSEvent) => { const results = await Promise.allSettled( event.Records.map(async (record) => { const message = JSON.parse(record.body); await processMessage(message); }) ); // Return batch item failures for partial batch response const failures = results .map((result, index) => result.status === 'rejected' ? { itemIdentifier: event.Records[index].messageId } : null ) .filter(Boolean); return { batchItemFailures: failures }; };
DynamoDB Streams Handler
import type { DynamoDBStreamEvent, DynamoDBStreamHandler } from 'aws-lambda'; import { unmarshall } from '@aws-sdk/util-dynamodb'; export const streamHandler: DynamoDBStreamHandler = async ( event: DynamoDBStreamEvent ) => { for (const record of event.Records) { if (record.eventName === 'INSERT' && record.dynamodb?.NewImage) { const item = unmarshall(record.dynamodb.NewImage); await handleNewItem(item); } } };
S3 Handler
import type { S3Event, S3Handler } from 'aws-lambda'; export const s3Handler: S3Handler = async (event: S3Event) => { for (const record of event.Records) { const bucket = record.s3.bucket.name; const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, ' ')); await processS3Object(bucket, key); } };
DynamoDB Integration
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { DynamoDBDocumentClient, GetCommand, PutCommand, QueryCommand, UpdateCommand, } from '@aws-sdk/lib-dynamodb'; const client = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(client); const TABLE_NAME = process.env.TABLE_NAME!; // Get item async function getUser(userId: string) { const result = await docClient.send(new GetCommand({ TableName: TABLE_NAME, Key: { PK: `USER#${userId}`, SK: `USER#${userId}` }, })); return result.Item; } // Put item async function createUser(user: User) { await docClient.send(new PutCommand({ TableName: TABLE_NAME, Item: { PK: `USER#${user.id}`, SK: `USER#${user.id}`, ...user, createdAt: new Date().toISOString(), }, ConditionExpression: 'attribute_not_exists(PK)', })); } // Query with GSI async function getUserOrders(userId: string) { const result = await docClient.send(new QueryCommand({ TableName: TABLE_NAME, IndexName: 'GSI1', KeyConditionExpression: 'GSI1PK = :pk AND begins_with(GSI1SK, :sk)', ExpressionAttributeValues: { ':pk': `USER#${userId}`, ':sk': 'ORDER#', }, })); return result.Items ?? []; }
SAM Template
# template.yaml AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Globals: Function: Timeout: 30 Runtime: nodejs20.x MemorySize: 256 Architectures: - arm64 Environment: Variables: TABLE_NAME: !Ref UsersTable Resources: ApiFunction: Type: AWS::Serverless::Function Properties: Handler: dist/handlers/api.handler Events: GetUsers: Type: Api Properties: Path: /users Method: GET CreateUser: Type: Api Properties: Path: /users Method: POST Policies: - DynamoDBCrudPolicy: TableName: !Ref UsersTable Metadata: BuildMethod: esbuild BuildProperties: Minify: true Target: es2022 UsersTable: Type: AWS::DynamoDB::Table Properties: BillingMode: PAY_PER_REQUEST AttributeDefinitions: - AttributeName: PK AttributeType: S - AttributeName: SK AttributeType: S KeySchema: - AttributeName: PK KeyType: HASH - AttributeName: SK KeyType: RANGE Outputs: ApiUrl: Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod'
CDK Lambda
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 { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; export class ApiStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { super(scope, id); const table = new dynamodb.Table(this, 'UsersTable', { partitionKey: { name: 'PK', type: dynamodb.AttributeType.STRING }, sortKey: { name: 'SK', type: dynamodb.AttributeType.STRING }, billingMode: dynamodb.BillingMode.PAY_PER_REQUEST, }); const fn = new NodejsFunction(this, 'ApiHandler', { entry: 'src/handlers/api.ts', runtime: lambda.Runtime.NODEJS_20_X, architecture: lambda.Architecture.ARM_64, environment: { TABLE_NAME: table.tableName, }, bundling: { minify: true, }, }); table.grantReadWriteData(fn); new apigateway.LambdaRestApi(this, 'Api', { handler: fn, }); } }
Best Practices
| Practice | Implementation |
|---|---|
| Cold starts | Use ARM64, minimize dependencies, use provisioned concurrency for critical paths |
| Connections | Reuse SDK clients outside handler, use connection pooling |
| Error handling | Use structured error responses, implement retries with backoff |
| Logging | Use structured JSON logging, include request IDs |
| Security | Use IAM roles, validate input, encrypt sensitive data |
Common Workflows
New Lambda Function
- Create handler file with TypeScript types
- Add middleware for validation/error handling
- Configure SAM/CDK template
- Set up IAM permissions
- Deploy and test
Event-Driven Architecture
- Define event source (SQS, S3, DynamoDB Streams)
- Create event handler with proper typing
- Implement batch failure handling
- Configure DLQ for failed events
- Monitor with CloudWatch