aws-serverless

专长于构建可在AWS上投入生产的无服务器应用。涵盖Lambda函数、API网关、DynamoDB、SQS/SNS事件驱动模式、SAM/CDK部署及冷启动优化。

查看详情
name:aws-serverlessdescription:"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."source:vibeship-spawner-skills (Apache 2.0)

AWS Serverless

Patterns

Lambda Handler Pattern

Proper Lambda function structure with error handling

When to use: ['Any Lambda function implementation', 'API handlers, event processors, scheduled tasks']

javascript
// 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

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 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']

javascript
# 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 =

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']

yaml

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

javascript
// 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

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_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

IssueSeveritySolution
Issuehigh## Measure your INIT phase
Issuehigh## Set appropriate timeout
Issuehigh## Increase memory allocation
Issuemedium## Verify VPC configuration
Issuemedium## Tell Lambda not to wait for event loop
Issuemedium## For large file uploads
Issuehigh## Use different buckets/prefixes

    aws-serverless - Agent Skills