Node.js Serverless on AWS Lambda · Capstone Case Studies

Capstone: Move an Express API to Lambda, or Decide Not To

Evaluate migrating an existing Express.js API to Lambda and produce a migration plan or a reasoned 'no'.

Scenario

Example company: a B2B SaaS runs an Express.js API (60 routes, Node.js 22, PostgreSQL) on two always-on virtual machines behind a load balancer. Traffic is spiky: near zero at night and weekends, bursts of 200 requests per second during business hours, with a few report endpoints that run for up to 4 minutes. There is also a WebSocket endpoint for live notifications.

Leadership asks: "Should we move to serverless to cut costs and stop patching servers?"

Requirements

  • No downtime during migration; customers must not notice.
  • Keep p95 latency under 300 ms for normal endpoints.
  • Reduce operational toil (patching, scaling) and ideally cost.
  • Present a recommendation with evidence, not just a technology preference.

Constraints

  • The database stays PostgreSQL (RDS), with a 500-connection limit.
  • Four engineers, part-time, over one quarter.
  • The Express app uses sessions stored in memory and writes temporary files to local disk.

Deliverables

  1. Your recommendation (Lambda, containers, hybrid, or stay) with the reasoning and the data you would gather.
  2. The application changes required before any move (state, files, connections, long requests, WebSockets).
  3. A migration plan that avoids downtime, including how traffic is shifted and rolled back.
  4. Risks and how you would measure success after the move.

Hints

  • Not every endpoint has to move in the same way.
  • Look at what in the app assumes a long-lived server.
  • Connections per instance times instances must stay below 500.

Draft each deliverable below before revealing the model answer and rubric.

Further reading: Amazon RDS Proxy · Lambda function URLs

Deliverables

Make and defend a recommendation.

Model answer

  • Gather: request rate by hour, per-route latency and duration distribution, concurrency, current VM and operations cost, and incident history.
  • A reasonable recommendation for this profile is a hybrid: move the normal request/response routes to Lambda behind an HTTP API (spiky traffic and idle nights favour per-request billing and remove patching), run the 4-minute reports as asynchronous jobs (SQS or Step Functions, results to S3), and move WebSockets to API Gateway WebSocket APIs or a small container service. Alternatively, containers on Fargate or Cloud Run if steady load grows or the team prefers one runtime model.
  • Decide with a cost model on real traffic and a prototype measuring latency, not on preference.

Rubric

Strong answers base the decision on the traffic shape and route characteristics, consider containers fairly, and split the problem (normal routes, long reports, WebSockets) instead of a single all-or-nothing answer.

List the application changes needed first.

Model answer

  • Sessions: move from memory to a shared store (DynamoDB or Redis) or stateless JWT sessions, because requests land on different instances.
  • Local files: write to S3 (or /tmp only for transient scratch data within one request).
  • Database connections: use RDS Proxy, a pool size of 1 per execution environment, and reserved concurrency so total connections stay under the limit.
  • Long reports: convert to async jobs with presigned download URLs.
  • Configuration and secrets: environment-independent build, secrets via Secrets Manager with caching.
  • Packaging: bundle with esbuild; wrap Express with an adapter (for example @codegenie/serverless-express) or move routes gradually to a lighter framework.

Rubric

Look for identification of every 'long-lived server' assumption (memory sessions, local disk, connection pools, long requests, WebSockets) and a concrete fix for each.

Plan a migration without downtime.

Model answer

  • Make the state changes (sessions, files) in the existing app first and deploy them on the VMs.
  • Deploy the Lambda version alongside the VMs. Route a small share of traffic (weighted DNS records or load balancer weighted target groups; or per-route path routing) to the new stack, starting with read-only routes.
  • Compare error rates and latency; increase gradually route by route; keep the VMs as instant rollback.
  • Move async reports and WebSockets in separate steps; decommission VMs after a stable period.

Rubric

Good plans move incrementally (strangler fig), keep rollback trivial, and change one dimension at a time.

Risks and success measures.

Model answer

  • Risks: cold-start latency on rarely used routes (mitigate with bundling, provisioned concurrency for critical paths), database connection storms (RDS Proxy, concurrency caps), cost surprises at higher steady load, team unfamiliarity (training, runbooks).
  • Success measures: p95 latency per route versus baseline, error rate, monthly cost compared with the VM baseline, hours spent on patching and scaling, deployment frequency and lead time.

Rubric

Strong answers define measurable success criteria agreed before the migration and revisit the decision with data afterwards.

Open in the app to mark lessons complete, take notes and track your progress.