Skip to content

AWS Lambda Cheat Sheet

AWS Lambda runs Node.js handlers on demand: export an async function receiving event and context, return a response or throw for API Gateway and other triggers.

How to use this AWS Lambda cheat sheet

Cold starts occur when AWS provisions a new execution environment—minimize bundle size, lazy-load heavy SDK clients, and use provisioned concurrency for latency-sensitive paths. Environment variables store config; secrets belong in Secrets Manager or SSM Parameter Store, not hard-coded.

IAM execution roles grant least-privilege permissions per function. API Gateway proxy events wrap HTTP request fields in event. Layers share dependencies across functions. Set timeout and memory—memory also scales CPU proportionally.

Quick AWS Lambda example

export const handler = async (event, context) => {
  context.callbackWaitsForEmptyEventLoop = false;
  const body = JSON.parse(event.body ?? '{}');
  const id = event.pathParameters?.id;
  return {
    statusCode: 200,
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ id, received: body }),
  };
};

Handler Signature & Response

Element Example Notes
Handler export export const handler = async (event, context) => {} CommonJS module.exports.handler also works
event Trigger-specific JSON payload API Gateway, S3, SQS shapes differ
context context.awsRequestId, getRemainingTimeInMillis() Request metadata and deadline
Return (sync) return { statusCode: 200, body: "ok" } API Gateway proxy integration response
callbackWaitsForEmptyEventLoop false for DB pools Exit without waiting for open handles
Structured errors throw new Error("fail") → 502 from API GW Map to statusCode in try/catch for 4xx
JSON body JSON.parse(event.body) Validate input; API GW may base64-encode binary
Logging console.log(JSON.stringify({ reqId: context.awsRequestId })) CloudWatch Logs capture stdout

Cold Starts, Env & IAM

Topic Example Notes
Cold start First invoke or after idle scale-down Shrink bundle; avoid top-level heavy imports
Provisioned concurrency Pre-warmed execution environments Costs more; cuts tail latency
Env vars process.env.TABLE_NAME Set in function config or serverless.yml
Secrets Secrets Manager ARN in env Fetch at cold start and cache in global scope
Execution role lambda.amazonaws.com trust policy Attach AWSLambdaBasicExecutionRole + custom policies
Least privilege DynamoDB table-scoped actions Avoid AdministratorAccess on Lambda roles
VPC config Subnet + security group Adds ENI cold start latency; needed for private RDS
ARM64 (Graviton) architectures: [arm64] Often better price/performance for Node

API Gateway Event & Layers

Field Example Purpose
httpMethod event.httpMethod === "POST" Route by verb in single Lambda
path event.path Resource path; use pathParameters for {id}
pathParameters event.pathParameters.id REST API route params
queryStringParameters event.queryStringParameters?.page Query string map (may be null)
headers event.headers.authorization Case-insensitive in API GW HTTP API v2
requestContext event.requestContext.authorizer JWT/Cognito claims after authorizer
Layer arn:aws:lambda:region:acct:layer:deps:1 Shared node_modules up to 250 MB unzipped total
Layer path /opt/nodejs/node_modules Node.js layer mount location

Timeout, Memory & Limits

Setting Example Notes
Timeout timeout: 30 seconds max 900 Set below upstream client timeout
Memory memorySize: 512 MB (128–10240) More memory = more CPU and cost
Ephemeral storage /tmp up to 10 GB Temp files; cleared between invocations maybe reused
Concurrency limit Reserved vs account limit Throttle with 429 when exceeded
Payload limit 6 MB sync invoke request/response Use S3 for large bodies
DLQ SQS or SNS on async failure Capture failed async invocations
Idempotency Store event id in DynamoDB Safe retries from SQS/Lambda pollers
X-Ray AWS_XRAY_TRACING_NAME Trace cold starts and downstream calls

Reuse SDK client outside handler

import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';

const doc = DynamoDBDocumentClient.from(new DynamoDBClient({}));

export const handler = async (event) => {
  await doc.send(new PutCommand({ TableName: process.env.TABLE, Item: event.item }));
  return { statusCode: 201, body: JSON.stringify({ ok: true }) };
};

Initialize clients in global scope so warm invocations skip construction cost.

SQS batch partial failure

export const handler = async (event) => {
  const failures = [];
  for (const record of event.Records) {
    try { await process(JSON.parse(record.body)); }
    catch { failures.push({ itemIdentifier: record.messageId }); }
  }
  return { batchItemFailures: failures };
};

Report batchItemFailures so only failed messages retry (Lambda SQS trigger).

Serverless Framework function stub

functions:
  api:
    handler: src/handler.main
    timeout: 29
    memorySize: 512
    environment:
      TABLE_NAME: ${self:custom.tableName}
    events:
      - httpApi:
          path: /items/{id}
          method: get

Keep HTTP timeout (29s) below API Gateway 30s limit.

Common mistakes

  • Creating new database connections on every invocation instead of reusing global clients.
  • Setting callbackWaitsForEmptyEventLoop true with open HTTP agents, delaying freeze and billing.
  • Granting Lambda roles broad s3:* or dynamodb:* instead of resource-scoped policies.
  • Ignoring async invocation failures without DLQ or CloudWatch alarms.

Key takeaways

  • Export async handler; parse API Gateway event fields for HTTP APIs.
  • Reuse SDK clients and secrets cache in global scope to reduce cold-start work.
  • Right-size memory and timeout; memory increases CPU allocation.
  • Layers share dependencies; IAM roles must follow least privilege per function.

Pro Tip

Enable Lambda Power Tuning (open-source tool) to find the memory sweet spot where duration drops enough to offset higher per-ms cost.