SST Infrastructure
Reggie's AWS infrastructure is defined in sst.config.ts using SST v4.2.0.
Infrastructure Diagram
graph TB
subgraph "SST Resources"
subgraph "Networking"
VPC["ReggieVpc<br/>sst.aws.Vpc<br/>10.0.0.0/16"]
NAT1["EC2 NAT Instance 1"]
NAT2["EC2 NAT Instance 2"]
end
subgraph "Database"
DB["ReggieDb<br/>sst.aws.Postgres.v1<br/>Aurora Serverless v2"]
end
subgraph "API"
APIGW["ReggieApi<br/>sst.aws.ApiGatewayV2"]
API_FN["API Route Lambda<br/>Node.js 22, arm64"]
end
subgraph "Services"
VAL["ReggieValuation<br/>sst.aws.Function<br/>Python 3.11, arm64"]
MIG["ReggieDbMigrator<br/>sst.aws.Function<br/>Python 3.11, x86_64"]
end
subgraph "Frontends"
WEB["ReggieWeb<br/>sst.aws.Nextjs"]
ADMIN["ReggieAdmin<br/>sst.aws.Nextjs"]
end
subgraph "Secrets (12)"
SEC["SST Secrets<br/>-> SSM Parameter Store"]
end
end
VPC --> NAT1
VPC --> NAT2
VPC --> DB
VPC --> API_FN
VPC --> VAL
VPC --> MIG
APIGW --> API_FN
API_FN --> DB
VAL --> DB
MIG --> DB
Resource Map
Resource
SST Component
AWS Service
Config
ReggieVpc
sst.aws.Vpc
VPC + EC2 NAT
2 AZs, ec2 NAT (~$8/mo)
ReggieDb
sst.aws.Postgres.v1
Aurora Serverless v2
PostgreSQL 17, encrypted, 0.5-4 ACU
ReggieApi
sst.aws.ApiGatewayV2
API Gateway V2
CORS, custom domain
API route
Lambda (ZIP)
Node.js 22
Hono + Drizzle, arm64, 1024 MB
ReggieValuation
sst.aws.Function
Lambda (Container)
LightGBM, arm64, 1536 MB
ReggieDbMigrator
sst.aws.Function
Lambda (Container)
Alembic, x86_64, 512 MB, 300s timeout
ReggieWeb
sst.aws.Nextjs
CloudFront + Lambda + S3
Next.js web app
ReggieAdmin
sst.aws.Nextjs
CloudFront + Lambda + S3
Next.js admin app
Database Configuration
graph LR
subgraph "Production"
PROD_DB["Aurora Serverless v2<br/>0.5-4 ACU<br/>Encrypted: Yes<br/>Backup: 14 days<br/>Deletion Protection: Yes"]
end
subgraph "Staging"
STG_DB["Aurora Serverless v2<br/>0.5-2 ACU<br/>Encrypted: Yes<br/>Backup: 7 days<br/>Deletion Protection: Yes"]
end
subgraph "Local Dev"
DEV_DB["Docker PostgreSQL<br/>localhost:54322"]
end
Key database settings (configured via sst.config.ts transform):
- Encryption at rest : Enabled on both stages
- Backup retention : 14 days (production), 7 days (staging)
- Deletion protection : Enabled for all deployed stages
- Scaling : 0.5 ACU minimum (scales to zero cost when idle)
- Password : URL-encoded in DATABASE_URL (SST generates passwords with special characters)
Secrets
12 secrets managed via SST Secrets (backed by AWS SSM Parameter Store):
# Set a secret for a stage
sst secret set ClerkSecretKey sk_live_... --stage staging
# List secrets for a stage
sst secret list --stage staging
Secret
Purpose
ClerkPublishableKey
Frontend Clerk auth
ClerkSecretKey
Backend Clerk auth
ClerkWebhookSecret
Clerk webhook verification
R2Endpoint
Cloudflare R2 storage endpoint
R2AccessKeyId
R2 access credentials
R2SecretAccessKey
R2 secret credentials
StripeSecretKey
Payment processing
StripeWebhookSecret
Stripe webhook verification
ResendApiKey
Email delivery
DvlaApiKey
DVLA vehicle enquiry
SecretKey
App-level signing
Dev vs Deployed
Resource
Deployed (staging/production)
Local (make dev)
Database
Aurora Serverless v2 (VPC)
Docker Postgres (localhost:54322)
API
Lambda (Node.js) via API Gateway
Hono dev server (localhost:8000)
Valuation
Lambda (Container)
Local Python process
Frontends
CloudFront + Lambda
Next.js dev servers
NAT
EC2 NAT instances
N/A (no VPC locally)
Stages
Stage
Trigger
Removal Policy
NAT Type
production
Manual workflow dispatch
retain
ec2
staging
Push to main
remove
ec2
<name>
Manual sst dev / sst deploy
remove
ec2
Cost Estimate (per stage)
Component
Monthly Cost
Notes
Aurora Serverless v2
~$43
0.5 ACU minimum
EC2 NAT (2x)
~$8
t4g.nano instances
Lambda
~$1-5
Pay per invocation
API Gateway
~$1
Pay per request
CloudFront
~$1
Pay per request
S3
~$1
Static assets
Total
~$55/stage
Domain Configuration
graph LR
subgraph "Cloudflare DNS (proxied)"
D1["getreggie.io"] --> WEB["ReggieWeb CloudFront"]
D2["admin.getreggie.io"] --> ADMIN["ReggieAdmin CloudFront"]
D3["api.getreggie.io"] --> API["ReggieApi API Gateway"]
D4["staging.getreggie.io"] --> SWEB["Staging Web"]
D5["staging-admin.getreggie.io"] --> SADMIN["Staging Admin"]
D6["staging-api.getreggie.io"] --> SAPI["Staging API"]
end
Domain
Stage
Points To
getreggie.io
production
CloudFront (Web)
admin.getreggie.io
production
CloudFront (Admin)
api.getreggie.io
production
API Gateway
staging.getreggie.io
staging
CloudFront (Web)
staging-admin.getreggie.io
staging
CloudFront (Admin)
staging-api.getreggie.io
staging
API Gateway