Lambda Execution Model
Containers are created (cold start ~300ms), then reused (warm ~0ms). Initialize clients outside handlers.
Cold Start Optimization
// Initialize OUTSIDE handler — reused on warm invocations
const db = DynamoDBDocumentClient.from(new DynamoDBClient({ maxAttempts: 3 }))
const pgPool = new Pool({ connectionString: process.env.DATABASE_URL, max: 1 })
export const handler = async (event: APIGatewayEvent) => {
// db and pgPool are already initialized — no cold start overhead
}
SQS Partial Batch Failures
export const handler = async (event: SQSEvent) => {
const failures: SQSBatchItemFailure[] = []
await Promise.allSettled(event.Records.map(async (record) => {
try {
await processMessage(JSON.parse(record.body))
} catch (err) {
failures.push({ itemIdentifier: record.messageId })
}
}))
return { batchItemFailures: failures }
}
Cached SSM Secrets
const secretCache = new Map<string, string>()
async function getSecret(name: string) {
if (secretCache.has(name)) return secretCache.get(name)!
const { Parameter } = await ssm.send(new GetParameterCommand({ Name: name, WithDecryption: true }))
secretCache.set(name, Parameter!.Value!)
return Parameter!.Value!
}
Cost Optimization
| Change | Savings |
|---|---|
| 128MB → 512MB memory | Often -60% total cost |
| ARM64 architecture | -20% cost |
| Reserved Concurrency | Prevents runaway scaling |
-> Encode Lambda vars with the Base64 Converter.