Serverless Architecture Patterns: AWS Lambda Best Practices
Design production-ready serverless applications with AWS Lambda including patterns for API development, event processing, and cost optimization.
Serverless architecture eliminates infrastructure management but introduces new patterns and challenges. Here's how to build robust serverless applications.
Lambda Function Structure
import { APIGatewayProxyHandler } from "aws-lambda";
export const handler: APIGatewayProxyHandler = async (event, context) => {
// Disable waiting for event loop
context.callbackWaitsForEmptyEventLoop = false;
try {
const body = JSON.parse(event.body || "{}");
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,
body: JSON.stringify({ error: "Internal server error" }),
};
}
};Cold Start Optimization
Minimize cold starts with: smaller deployment packages, provisioned concurrency for critical paths, keeping functions warm with scheduled events, and using Lambda layers for shared dependencies.
# serverless.yml
functions:
api:
handler: handler.main
provisionedConcurrency: 5
layers:
- arn:aws:lambda:region:account:layer:dependencies:1Connection Pooling Outside Handler
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
// Initialize outside handler for reuse across invocations
const dynamodb = new DynamoDBClient({});
export const handler = async (event) => {
// Use the shared client
await dynamodb.send(new GetItemCommand({ ... }));
};Event-Driven Patterns
# SQS trigger with batch processing
functions:
processOrders:
handler: handlers/orders.process
events:
- sqs:
arn: !GetAtt OrdersQueue.Arn
batchSize: 10
maximumBatchingWindow: 5Error Handling and Retries
// Implement idempotency for retries
import { IdempotencyConfig } from "@aws-lambda-powertools/idempotency";
const config = new IdempotencyConfig({
eventKeyJmesPath: "body.orderId",
expiresAfterSeconds: 3600,
});
export const handler = makeIdempotent(async (event) => {
// Process order
}, config);Dead Letter Queues
functions:
processEvents:
handler: handler.process
onError: !GetAtt DeadLetterQueue.Arn
maximumRetryAttempts: 2API Gateway Integration Patterns
REST API: Traditional request/response with full API Gateway features.
HTTP API: Lower cost, faster, simpler for most use cases.
WebSocket API: Real-time bidirectional communication.
Cost Optimization
Right-size memory (more memory = more CPU = faster = potentially cheaper).
Use ARM64 architecture (Graviton2) for 34% better price/performance.
Implement caching at API Gateway level.
Use reserved concurrency to prevent runaway costs.
functions:
api:
handler: handler.main
memorySize: 1024
architecture: arm64
reservedConcurrency: 100Monitoring and Observability
import { Logger, Metrics, Tracer } from "@aws-lambda-powertools";
const logger = new Logger();
const metrics = new Metrics();
const tracer = new Tracer();
export const handler = async (event) => {
logger.info("Processing request", { event });
metrics.addMetric("OrdersProcessed", MetricUnits.Count, 1);
const segment = tracer.getSegment();
// Process with X-Ray tracing
};NyxaLabs Serverless Expertise
We design and implement serverless architectures that scale automatically while minimizing costs. From API development to event processing systems, our team delivers production-ready solutions. Contact us for serverless consulting.