Serverless Node.js
Serverless means running code without managing a server — you deploy a function, and the platform (AWS Lambda, GCP Cloud Functions, Vercel Edge, Cloudflare Workers) runs it on demand, scales it to zero when idle, and charges per invocation. For the right workload — event-driven processing, spiky traffic, webhooks, API routes — it removes almost all operational overhead. For the wrong workload — long-running processes, stateful connections, cold-start-sensitive paths — it's a poor fit. This page covers how serverless Node works, the event model, adapting an Express app, cold starts and how to mitigate them, and the execution constraints you must design around.
How serverless Node works
A basic Lambda handler
// A serverless function is a MODULE EXPORT, not a long-running server.
// The platform calls it on each event and tears it down when idle.
export const handler = async (event, context) => {
// 'event' varies by trigger: API Gateway request, S3 event, SQS message, timer...
const name = event.queryStringParameters?.name ?? 'world'
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: `Hello, ${name}!` }),
}
}Adapting Express for serverless
// Option A: use an adapter that wraps your Express app as a Lambda handler.
import serverlessExpress from '@vendia/serverless-express'
import app from './app' // your normal Express app (no .listen())
export const handler = serverlessExpress({ app })
// Option B: serverless frameworks (SST, Architect) handle routing natively.
// Option C: use a framework designed for serverless (Next.js API routes, Hono).Cold starts — the main serverless gotcha
Cold start sequence (only when the container is recycled): Platform allocates a container → downloads your deployment package → starts Node runtime → executes module-level code (requires, DB connections, SDK clients) → runs your handler function ─────────────────────────────────────── can take 200ms–2s+ for Node Warm invocation (container already running): → runs your handler function ← typically 1–10ms overhead
Execution constraints to design around
Constraint | Implication |
|---|---|
Timeout (e.g. 15 min max on Lambda) | No long-running processes; offload to a queue/background job |
Ephemeral filesystem ( | Don't write permanent files; use S3/storage |
No persistent connections between invocations | Use connection pooling proxies (RDS Proxy, PgBouncer) for databases |
Stateless / no shared memory | All shared state in external services (Redis, DB) |
Concurrency = copies, not threads | High concurrency = many parallel cold Lambda containers |