Skip to content

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