Files
esdp/serverless

Serverless TypeScript Project

This folder contains AWS Lambda functions deployed via the Serverless Framework, written in TypeScript.

Setup

This project is configured with TypeScript, ESLint, and Prettier independently from the main project.

Prerequisites

  • Node.js 22.x or higher
  • npm or yarn

Installation

npm install

Development

Available Scripts

  • npm run build - Compile TypeScript to JavaScript
  • npm run type-check - Run TypeScript type checking without emitting files
  • npm run lint - Run ESLint on TypeScript files
  • npm run lint:fix - Run ESLint with auto-fix
  • npm run format - Format code with Prettier
  • npm run format:check - Check if code is formatted correctly

Project Structure

src/
  handlers/          # Lambda function handlers
    vehicleType.ts   # Vehicle type lookup handler
    scrub.ts         # Estimate scrubbing handler
    emsupload.ts     # File upload presigned URL handler
  lib/               # Shared library code
    vehicleTypes/    # Vehicle type utilities
    db.ts            # Database utilities

Deployment

The project uses serverless-esbuild for bundling TypeScript code for deployment.

# Deploy to dev stage
sls deploy --stage dev

# Deploy to production
sls deploy --stage prod

RDS + Drizzle (Postgres)

This project provisions a private Postgres RDS instance and the networking needed for Lambdas to reach it.

What gets created

Defined in serverless.yml:

  • A dedicated VPC with 2 public subnets + 2 private subnets
  • A NAT Gateway for private-subnet egress
  • Security groups:
    • Lambda SG (egress all)
    • RDS SG (allows inbound 5432 only from the Lambda SG)
  • An RDS Postgres instance:
    • DeletionProtection: true
    • DeletionPolicy: Snapshot / UpdateReplacePolicy: Snapshot
    • AutoMinorVersionUpgrade: true (minor updates)
    • Not publicly accessible
  • An RDS Proxy in the same VPC (Lambdas connect to the proxy, proxy connects to RDS)
  • A Secrets Manager secret for the RDS master user (generated password)

Note: RDS + NAT Gateway incur AWS costs.

Drizzle files

  • Schema: src/db/schema/**/*.ts
  • Drizzle config: drizzle.config.ts
  • Generated migrations (SQL): drizzle/ (packaged for Lambda)

Install deps

cd serverless
npm install

Generate a migration (no DB connection required)

Drizzle can generate SQL migrations by diffing your schema files.

cd serverless
npm run db:generate

This writes SQL into serverless/drizzle/.

Deploy the database

cd serverless
sls deploy --stage dev

RDS creation can take several minutes.

Because the RDS instance is in private subnets, it is not directly reachable from your laptop by default. The repo includes an internal migration Lambda (dbMigrate) that runs in the same VPC as the database.

cd serverless
sls invoke -f dbMigrate --stage dev

Sanity check connectivity

cd serverless
sls invoke -f dbPing --stage dev

Local migrations (optional)

If you set up network access to the private RDS instance (e.g., via Client VPN or an SSM tunnel through a bastion host), you can run Drizzle migrations locally:

export DATABASE_URL='postgres://USER:PASSWORD@HOST:5432/esdp'
npm run db:migrate

Deletion protection behavior

  • sls remove will not be able to delete the DB instance while deletion protection is enabled.
  • To intentionally remove it later, you must first disable deletion protection in serverless.yml and redeploy, then remove the stack.

Stage-specific DB name

The Postgres database name comes from the stage param db_name in serverless.yml (e.g. esdpdev, esdpalpha, esdpbeta, esdpprod).

Local Development

# Run serverless offline
sls dev

Configuration

  • TypeScript: Configured in tsconfig.json
  • ESLint: Configured in eslint.config.mjs (ESM flat config)
  • Prettier: Configured in .prettierrc.json
  • Serverless: Configured in serverless.yml

Code Quality

This project enforces:

  • TypeScript strict mode
  • ESLint rules for TypeScript
  • Prettier formatting
  • No unused variables or parameters (except those prefixed with _)

Environment Variables

See serverless.yml for environment-specific configuration.