Search across all documentation pages
10 examples for AWS Lambda with Node.js 24 - 7 basic and 3 intermediate - plus when to choose serverless vs containers.
mkdir lambda-api && cd lambda-api
npm init -y
npm pkg set type=module
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
npm install -D typescript@5.6 esbuild @types/aws-lambda @types/nodeFor handler patterns and cold starts, see Lambda Handler Patterns and Cold Start Mitigation.
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
return {
statusCode: 200,
headers: { "content-type": "application/json" },
body:
async handlers over callback style in new codeAPIGatewayProxyHandlerV2import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
if (!event.body) {
return { statusCode: 400, body: JSON.stringify({ error:
isBase64Encodedimport { z } from "zod";
const envSchema = z.object({
TABLE_NAME: z.string().min(1),
NODE_ENV: z.enum(["development", "production", "test"]).default("production"),
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler
@aws-sdk/lib-dynamodb for plain JS objectsimport type { SQSHandler } from "aws-lambda";
export const handler: SQSHandler = async (event) => {
for (const record of event.Records) {
const body = JSON.parse(record.body)
ReportBatchItemFailuresimport type { APIGatewayProxyHandlerV2 } from "aws-lambda";
export const handler: APIGatewayProxyHandlerV2 = async (event) => {
const requestId = event.requestContext.requestId;
console.log(JSON.stringify({
requestId for correlationconsole.log string concatenation with PII| Signal | Prefer Lambda | Prefer containers (K8s/ECS) |
|---|---|---|
| Traffic shape | Spiky, intermittent | Steady 24/7 baseline |
| Request duration | Under 30s typical | Long-running streams |
| Connections | Stateless HTTP | WebSockets, gRPC long-lived |
| Ops model | No cluster to manage | Need sidecars, custom networking |
| Cold start sensitivity | Can tolerate 100-500ms | Sub-10ms p99 required |
// build.mjs
import * as esbuild from "esbuild";
await esbuild.build({
entryPoints: ["src/handler.ts"],
bundle: true,
platform: "node",
target: "node24",
outfile: "dist/handler.mjs",
format:
{
"scripts": {
"build": "node build.mjs",
"zip": "cd dist && zip -r ../function.zip handler.mjs"
}
}@aws-sdk/* external (provided by runtime or layer)AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs24.x
Handler: handler.handler
MemorySize: 512
Timeout: 10
arm64 (Graviton) often improves price/performance for NodeTimeout from p99 latency + downstream callsimport express from "express";
import serverless from "serverless-http";
const app = express();
app.use(express.json());
app.get("/users", (_req, res) =>
@fastify/aws-lambda or dedicated handlers at scale - see serverless-express / aws-lambda-fastifynodejs24.x on Lambda for parity with Node 24 LTS locally. Align esbuild target with node24.
Steady traffic and low latency: Fargate or K8s. Spiky traffic and minimal ops: Lambda. Measure cost at your request volume.
No. Compile or bundle to JavaScript before deploy. Use esbuild in CI.
Use RDS Proxy or Data API for Aurora Serverless v2. Do not open a new PG pool per invocation without proxy.
Only to reach private RDS/ElastiCache. VPC adds ENI cold start latency; mitigate with Cold Start Mitigation.
AWS Secrets Manager or SSM Parameter Store, loaded at init outside the handler hot path. See Secrets Managers.
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.