Specification
7. Infrastructure

7. Infrastructure & DevOps

7.1 CI/CD Pipeline

Tool: GitHub Actions

RepoVisibilityWhy
BackendPrivateSecurity sensitive business logic
FrontendPublicUnlimited CI minutes + portfolio value

Workflow Files

FileTriggerSteps
ci.ymlPush to any branchTypeCheck → ESLint → Unit Tests → Integration Tests
deploy-staging.ymlPush to stagingCI + Build + Deploy Fly.io staging + DB migrations + E2E tests
deploy-prod.ymlPush to mainCI + Build + Deploy Fly.io prod + DB migrations + Smoke tests

Branch Strategy

BranchPurposeDeploys To
feature/*New featuresNo deploy
fix/*Bug fixesNo deploy
chore/*Maintenance, dependenciesNo deploy
hotfix/*Urgent production fixesmain directly
devIntegration branchNo deploy
stagingPre-productionFly.io staging + Vercel Preview
mainProductionFly.io prod + Vercel Production
feature/* ─┐
fix/*      ─┼──► dev ──► staging ──► main
chore/*    ─┘
hotfix/*   ──────────────────────────► main (emergency)

Pre-commit hooks via Husky + lint-staged: ESLint --fix, Prettier --write, TypeScript --noEmit. Commit is blocked if any check fails — catches issues before they reach CI.

Example CI Workflow

# .github/workflows/ci.yml
name: CI
on: [push]
 
jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: npx tsc --noEmit
      - run: npx eslint .
      - run: npm test -- --coverage --passWithNoTests
      - run: npm run test:integration

7.2 Environment Variables

Backend (Fly.io)

VariablePurpose
DATABASE_URLPostgreSQL connection string
JWT_SECRETJWT signing key
COOKIE_SECRETSession cookie signing
STRIPE_SECRET_KEYStripe server-side key
STRIPE_WEBHOOK_SECRETWebhook signature verification
RESEND_API_KEYResend transactional email
R2_ACCOUNT_IDCloudflare R2 account
R2_ACCESS_KEY_IDR2 access key
R2_SECRET_ACCESS_KEYR2 secret
R2_BUCKET_NAMER2 bucket name
R2_PUBLIC_URLR2 public CDN URL
STORE_CORSAllowed store origin
ADMIN_CORSAllowed admin origin
AUTH_CORSAllowed auth origin

Frontend (Vercel)

VariablePurpose
NEXT_PUBLIC_MEDUSA_BACKEND_URLMedusa API base URL
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEYMedusa store publishable key
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYStripe publishable key
NEXT_PUBLIC_STORE_URLStorefront base URL
⚠️

NEXT_PUBLIC_ prefix exposes the variable to the browser. Never put secret keys in NEXT_PUBLIC_ variables.

7.3 Database Reliability

ConcernSolutionPhase
Connection poolingSupabase PgBouncer (built-in, free)1+
Uptime target99%1
Uptime target99.9%2
Uptime target99.99%3
Read replicasSupabase Pro tier2+
Automated backupsSupabase daily + PITR 7 days2+
Manual backupsWeekly export from Supabase dashboard1

Backup Retention

FrequencyRetention
Daily7 days
Weekly4 weeks
Monthly12 months
Yearly7 years (ATO requirement)

7.4 Monitoring

ToolMonitorsPhase
Better UptimeUptime, response time, SSL expiry1+
SentryFrontend + backend errors, stack traces1+
Vercel AnalyticsCore Web Vitals, page performance1+
New RelicAPM, database queries, full tracing3
DatadogFull observability stack3+