7. Infrastructure & DevOps
7.1 CI/CD Pipeline
Tool: GitHub Actions
| Repo | Visibility | Why |
|---|---|---|
| Backend | Private | Security sensitive business logic |
| Frontend | Public | Unlimited CI minutes + portfolio value |
Workflow Files
| File | Trigger | Steps |
|---|---|---|
ci.yml | Push to any branch | TypeCheck → ESLint → Unit Tests → Integration Tests |
deploy-staging.yml | Push to staging | CI + Build + Deploy Fly.io staging + DB migrations + E2E tests |
deploy-prod.yml | Push to main | CI + Build + Deploy Fly.io prod + DB migrations + Smoke tests |
Branch Strategy
| Branch | Purpose | Deploys To |
|---|---|---|
feature/* | New features | No deploy |
fix/* | Bug fixes | No deploy |
chore/* | Maintenance, dependencies | No deploy |
hotfix/* | Urgent production fixes | main directly |
dev | Integration branch | No deploy |
staging | Pre-production | Fly.io staging + Vercel Preview |
main | Production | Fly.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:integration7.2 Environment Variables
Backend (Fly.io)
| Variable | Purpose |
|---|---|
DATABASE_URL | PostgreSQL connection string |
JWT_SECRET | JWT signing key |
COOKIE_SECRET | Session cookie signing |
STRIPE_SECRET_KEY | Stripe server-side key |
STRIPE_WEBHOOK_SECRET | Webhook signature verification |
RESEND_API_KEY | Resend transactional email |
R2_ACCOUNT_ID | Cloudflare R2 account |
R2_ACCESS_KEY_ID | R2 access key |
R2_SECRET_ACCESS_KEY | R2 secret |
R2_BUCKET_NAME | R2 bucket name |
R2_PUBLIC_URL | R2 public CDN URL |
STORE_CORS | Allowed store origin |
ADMIN_CORS | Allowed admin origin |
AUTH_CORS | Allowed auth origin |
Frontend (Vercel)
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_MEDUSA_BACKEND_URL | Medusa API base URL |
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY | Medusa store publishable key |
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY | Stripe publishable key |
NEXT_PUBLIC_STORE_URL | Storefront base URL |
⚠️
NEXT_PUBLIC_ prefix exposes the variable to the browser. Never put secret keys in NEXT_PUBLIC_ variables.
7.3 Database Reliability
| Concern | Solution | Phase |
|---|---|---|
| Connection pooling | Supabase PgBouncer (built-in, free) | 1+ |
| Uptime target | 99% | 1 |
| Uptime target | 99.9% | 2 |
| Uptime target | 99.99% | 3 |
| Read replicas | Supabase Pro tier | 2+ |
| Automated backups | Supabase daily + PITR 7 days | 2+ |
| Manual backups | Weekly export from Supabase dashboard | 1 |
Backup Retention
| Frequency | Retention |
|---|---|
| Daily | 7 days |
| Weekly | 4 weeks |
| Monthly | 12 months |
| Yearly | 7 years (ATO requirement) |
7.4 Monitoring
| Tool | Monitors | Phase |
|---|---|---|
| Better Uptime | Uptime, response time, SSL expiry | 1+ |
| Sentry | Frontend + backend errors, stack traces | 1+ |
| Vercel Analytics | Core Web Vitals, page performance | 1+ |
| New Relic | APM, database queries, full tracing | 3 |
| Datadog | Full observability stack | 3+ |