Lambda Fundamentals
Lambda Fundamentals AWS Lambda runs code in response to events without managing servers. Understanding the handler signature, context object, and execution envi…
Lambda Fundamentals
AWS Lambda runs code in response to events without managing servers. Understanding the handler signature, context object, and execution environment lifecycle is the foundation for writing reliable Lambda functions.
Handler Signatures
// Node.js 20 — async handler (preferred)
export const handler = async (event, context) => {
console.log("Event:", JSON.stringify(event, null, 2));
console.log("Function name:", context.functionName);
console.log("Remaining time (ms):", context.getRemainingTimeInMillis());
// Return value becomes the response (for sync invocations like API GW)
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: "Hello from Lambda" }),
};
};
// Node.js — callback style (legacy, avoid for new code)
exports.handler = function(event, context, callback) {
callback(null, { statusCode: 200, body: "OK" }); // (error, result)
};
// context object key properties:
// context.functionName — e.g. "my-function"
// context.functionVersion — "$LATEST" or version number
// context.invokedFunctionArn — full ARN of the invoked function/alias
// context.awsRequestId — unique request ID for this invocation
// context.logGroupName — CloudWatch log group
// context.logStreamName — CloudWatch log stream (unique per instance)
// context.memoryLimitInMB — configured memory
// context.getRemainingTimeInMillis() — ms until timeout# Python 3.12 handler
# def handler(event: dict, context) -> dict:
# import json
# print(f"Request ID: {context.aws_request_id}")
# print(f"Remaining time: {context.get_remaining_time_in_millis()}ms")
# return {"statusCode": 200, "body": json.dumps({"message": "OK"})}
# Go handler
# package main
# import (
# "context"
# "github.com/aws/aws-lambda-go/lambda"
# "github.com/aws/aws-lambda-go/events"
# )
# func handler(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
# return events.APIGatewayProxyResponse{StatusCode: 200, Body: "OK"}, nil
# }
# func main() { lambda.Start(handler) }
# Invoke Lambda from CLI
aws lambda invoke --function-name my-function --payload '{"key": "value"}' --cli-binary-format raw-in-base64-out output.json
cat output.json
# Invoke asynchronously (fire and forget)
aws lambda invoke --function-name my-function --invocation-type Event --payload '{"key": "value"}' --cli-binary-format raw-in-base64-out /dev/null
# View CloudWatch logs
aws logs tail /aws/lambda/my-function --followExecution Environment & Cold Starts
// Execution environment lifecycle:
// INIT phase: downloads code, starts runtime, runs initialization code (outside handler)
// INVOKE phase: runs handler for each invocation (environment reused if warm)
// SHUTDOWN: environment frozen, not immediately destroyed
// Cold start: new execution environment allocated (INIT + INVOKE)
// Warm start: existing environment reused (INVOKE only) — much faster
// Code OUTSIDE the handler runs only during cold start (initialization)
// Put expensive setup here (DB connections, SDK clients, config loading):
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
// This runs once per cold start, reused across warm invocations
const ddbClient = new DynamoDBClient({ region: "us-east-1" });
const docClient = DynamoDBDocumentClient.from(ddbClient);
// Cached config (avoid fetching on every invocation)
let config = null;
async function getConfig() {
if (!config) {
// Fetch from SSM/Secrets Manager only on cold start or cache miss
config = await fetchConfigFromSSM();
}
return config;
}
export const handler = async (event) => {
const cfg = await getConfig(); // Uses cached value on warm invocations
// ... business logic
};
// Lambda Function URL — invoke Lambda directly over HTTPS (no API Gateway)
// Provides a dedicated URL: https://<url-id>.lambda-url.<region>.on.aws
aws lambda create-function-url-config --function-name my-function --auth-type AWS_IAM # or NONE for public endpoints
# Returns: FunctionUrl: https://abc123.lambda-url.us-east-1.on.aws/