Event Sources & Triggers
Lambda integrates with virtually every AWS service. The event payload structure varies by source — knowing the shape of the event object for each trigger is critical for writing correct handler code.
API Gateway & S3
// API Gateway HTTP API (payload format version 2.0) event shape
{
"version": "2.0",
"routeKey": "POST /users",
"rawPath": "/users",
"rawQueryString": "page=1",
"headers": { "content-type": "application/json", ... },
"queryStringParameters": { "page": "1" },
"pathParameters": { "userId": "123" },
"body": "{"name": "Alice"}", // string, not parsed
"isBase64Encoded": false,
"requestContext": {
"accountId": "123456789012",
"http": { "method": "POST", "path": "/users", "sourceIp": "1.2.3.4" },
"requestId": "abc-123"
}
}
// Handler parsing API GW HTTP API event
export const handler = async (event) => {
const body = JSON.parse(event.body || "{}");
const userId = event.pathParameters?.userId;
const page = parseInt(event.queryStringParameters?.page || "1", 10);
// ...
return { statusCode: 201, body: JSON.stringify({ id: "new-user-id" }) };
};
// S3 event — triggered on object create/delete
{
"Records": [{
"eventSource": "aws:s3",
"eventName": "ObjectCreated:Put",
"s3": {
"bucket": { "name": "my-bucket" },
"object": {
"key": "uploads/image.png", // URL-encoded — decode before use
"size": 102400
}
}
}]
}
// S3 handler
export const handler = async (event) => {
for (const record of event.Records) {
const bucket = record.s3.bucket.name;
const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));
console.log(`Processing s3://${bucket}/${key}`);
// process image, extract metadata, etc.
}
};SQS, SNS & DynamoDB Streams
// SQS event — batch of messages (up to 10 by default)
{
"Records": [{
"messageId": "abc-123",
"body": "{"orderId": "order-456"}", // string, must be parsed
"attributes": {
"ApproximateReceiveCount": "1",
"SentTimestamp": "1703001600000"
},
"receiptHandle": "AQEBxxx..." // Used to delete message (Lambda does this automatically on success)
}]
}
// SQS handler with partial batch failure reporting
export const handler = async (event) => {
const failures = [];
for (const record of event.Records) {
try {
const payload = JSON.parse(record.body);
await processOrder(payload.orderId);
} catch (err) {
console.error("Failed:", record.messageId, err);
failures.push({ itemIdentifier: record.messageId });
}
}
// Return failed message IDs — Lambda will requeue only these
return { batchItemFailures: failures };
};
// Enable "Report batch item failures" in the SQS event source mapping
// SNS event — Lambda subscribed to a topic
{
"Records": [{
"EventSource": "aws:sns",
"Sns": {
"Message": "{"type": "user.created", "userId": "123"}",
"Subject": "User Event",
"TopicArn": "arn:aws:sns:us-east-1:123:my-topic"
}
}]
}
// DynamoDB Streams — process table changes
{
"Records": [{
"eventSource": "aws:dynamodb",
"eventName": "INSERT", // INSERT | MODIFY | REMOVE
"dynamodb": {
"Keys": { "pk": { "S": "USER#123" } },
"NewImage": { "pk": { "S": "USER#123" }, "name": { "S": "Alice" } },
"OldImage": null // null for INSERT
}
}]
}EventBridge & Step Functions
# EventBridge — serverless event bus
# Schedule a Lambda every 5 minutes (cron expression)
aws events put-rule --name "run-every-5-min" --schedule-expression "rate(5 minutes)" --state ENABLED
aws lambda add-permission --function-name my-function --statement-id EventBridgeInvoke --action lambda:InvokeFunction --principal events.amazonaws.com --source-arn arn:aws:events:us-east-1:123:rule/run-every-5-min
aws events put-targets --rule "run-every-5-min" --targets "Id=1,Arn=arn:aws:lambda:us-east-1:123:function:my-function"
# EventBridge event payload
# { "version": "0", "id": "...", "source": "aws.ec2", "detail-type": "EC2 Instance State-change Notification",
# "detail": { "instance-id": "i-123", "state": "running" } }
# Step Functions — orchestrate Lambda functions
# Define a state machine in JSON/YAML (ASL — Amazon States Language)
# Lambda invoked as a Task state, receives input, returns output to next state
# Supports parallel execution, error handling, wait states, and human approval steps
# Kinesis Data Streams — real-time streaming
# Lambda reads batches of records from a Kinesis shard
# Records contain base64-encoded data
# export const handler = async (event) => {
# for (const record of event.Records) {
# const data = Buffer.from(record.kinesis.data, "base64").toString("utf-8");
# const payload = JSON.parse(data);
# await processMetric(payload);
# }
# };Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free