Separate infrastructure to separate yaml and base schema.

This commit is contained in:
Patrick Fic
2026-01-14 14:52:49 -08:00
parent 66fcaaf8f4
commit fefbd45570
8 changed files with 847 additions and 451 deletions

View File

@@ -46,36 +46,51 @@ src/
The project uses `serverless-esbuild` for bundling TypeScript code for deployment.
```bash
# Deploy to dev stage
sls deploy --stage dev
# 1) Deploy shared infra (VPC + DB + Proxy + Secret) once
sls deploy --config serverless.infra.yml --stage shared
# Deploy to production
# 2) Deploy the application Lambdas per stage (dev/alpha/beta/prod)
sls deploy --stage dev
sls deploy --stage prod
```
## RDS + Drizzle (Postgres)
This project provisions a **private** Postgres RDS instance and the networking needed for Lambdas to reach it.
This project provisions a **shared private** Postgres RDS instance (one DB for all app stages) and the networking needed for Lambdas to reach it.
If you want direct access from your laptop, the infra stack also allows inbound Postgres from a single admin IP CIDR (default is the current value in `serverless.infra.yml`).
### What gets created
Defined in `serverless.yml`:
Defined in `serverless.infra.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)
- RDS Proxy SG (allows inbound `5432` only from the Lambda SG)
- RDS SG (allows inbound `5432` only from the Proxy SG)
- An RDS Postgres instance:
- `DeletionProtection: true`
- `DeletionPolicy: Snapshot` / `UpdateReplacePolicy: Snapshot`
- `AutoMinorVersionUpgrade: true` (minor updates)
- Not publicly accessible
- Publicly accessible (restricted to a single `admin_cidr`)
- 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.
### Direct DB access (your IP only)
Infra config includes an `admin_cidr` parameter (e.g. `70.36.57.88/32`) that is allowed to connect to port `5432`. The RDS instance is placed in public subnets so it can be reached directly, but security groups restrict it to that single CIDR.
To change it, edit `stages.shared.params.admin_cidr` in `serverless.infra.yml` and redeploy infra:
```bash
cd serverless
sls deploy --config serverless.infra.yml --stage shared
```
### Drizzle files
- Schema: `src/db/schema/**/*.ts`
@@ -104,7 +119,7 @@ This writes SQL into `serverless/drizzle/`.
```bash
cd serverless
sls deploy --stage dev
sls deploy --config serverless.infra.yml --stage shared
```
RDS creation can take several minutes.
@@ -137,12 +152,12 @@ 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.
- `sls remove --config serverless.infra.yml --stage shared` 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.infra.yml` and redeploy, then remove the infra stack.
### Stage-specific DB name
### Single shared DB
The Postgres database name comes from the stage param `db_name` in `serverless.yml` (e.g. `esdpdev`, `esdpalpha`, `esdpbeta`, `esdpprod`).
The DB name comes from the `shared` stage param `db_name` in `serverless.infra.yml` (defaults to `esdp`). All app stages connect to this same DB via CloudFormation outputs.
## Local Development
@@ -156,7 +171,8 @@ sls dev
- **TypeScript**: Configured in `tsconfig.json`
- **ESLint**: Configured in `eslint.config.mjs` (ESM flat config)
- **Prettier**: Configured in `.prettierrc.json`
- **Serverless**: Configured in `serverless.yml`
- **Serverless (app)**: Configured in `serverless.yml`
- **Serverless (infra)**: Configured in `serverless.infra.yml`
## Code Quality
@@ -169,3 +185,9 @@ This project enforces:
## Environment Variables
See `serverless.yml` for environment-specific configuration.
How To Deploy
Deploy infra once (shared DB + networking): cd serverless && sls deploy --config serverless.infra.yml --stage shared
Deploy/update Lambdas per environment without touching DB/VPC: cd serverless && sls deploy --stage dev (and similarly --stage prod, etc.)