arch-atlas
SaaS Atlas·Pillar 09 / 12

Infrastructure

Turborepo · Vercel · Cloudflare · Inngest · GitHub Actions

The right 2026 infra answer for a small SaaS team is unsexy on purpose: Turborepo monorepo, Vercel for the Next.js app, Cloudflare for static + edge auth, Inngest for background work, GitHub Actions for CI. No Kubernetes, no Terraform-for-everything, no in-house deploy tooling. Every hour spent on bespoke infra is an hour not spent on the product — buy back time aggressively.

7Nodes6Vendors0Decisions10Checklist2Flows

Primary stack

The default picks this pillar assumes

  • Turborepo
  • Cloudflare
  • Inngest

Alternates worth knowing

Swap in when scale, cost or constraints change

  • Nx
  • Trigger.dev
  • BullMQ
01
RepoMonorepo · Caching

Turborepo

One repo with multiple apps (web, mobile, marketing) + packages (db, ui, config). Turborepo handles the task graph, incremental builds, remote caching. Vercel's remote cache is free; Nx Cloud's is also free for OSS.

How it flows

step by step
  1. 01

    apps/web (Next.js), apps/marketing (Next.js), apps/mobile (Flutter, not in turbo), packages/db, packages/ui, packages/config.

    step
  2. 02

    pnpm workspaces for dep linking; pnpm install at the root.

    step
  3. 03

    turbo run build → topological build, parallel where independent, cached on hash.

    step
  4. 04

    Vercel remote cache: each CI run can pull other devs' / branches' cached outputs.

    step

Cases & edge cases

watch for these

Don't over-modularize — three apps + four packages is the sweet spot for years.

Avoid circular imports between packages — turborepo will flag, lint will too.

Mobile (Flutter) stays outside turbo's task graph — its own CI workflow.

Vendors & tools

what implements this

Turborepo

primarysite

Task runner + cache for JS monorepos.

Nx

alternate

More opinionated; over-engineered for 1-10 person teams.

Where it lives

code references
References
  • turbo.json
  • pnpm-workspace.yaml
  • packages/db/
02
DeployWeb + serverless

Vercel Deploys

Push to main → Vercel builds → if green, promotes to production. Every PR gets a preview URL with the full app on a unique subdomain. No special operations knowledge needed; you focus on the code.

How it flows

step by step
  1. 01

    git push → GitHub webhook to Vercel.

    step
  2. 02

    Vercel builds (with turbo remote cache) → runs the Next.js build.

    step
  3. 03

    Output: serverless functions (App Router route handlers, Server Actions) + edge functions (middleware) + static assets to CDN.

    step
  4. 04

    Atomic deploy: traffic shifts instantly; rollback = promote previous deployment.

    step

Cases & edge cases

watch for these

Preview URLs leak before launch — gate them with a Vercel Password or Cloudflare Access for marketing routes.

Cold starts on rarely-used routes — warm via cron pings or fluid compute (Vercel feature).

Vercel's pricing model: you pay for compute time. Watch image optimization + middleware execution.

Checklist

ship readiness
  • Preview deploys on every PR

    must
  • Production gated on green CI

    must
  • Rollback playbook documented

    must
03
EdgeDNS · CDN · Static · Workers

Cloudflare Edge

Cloudflare in front of Vercel: DNS, free DDoS protection, CDN for static assets, Workers for ultra-cheap edge logic (auth gating, A/B routing, geo redirects). Optional: Cloudflare R2 for cheap object storage (no egress).

How it flows

step by step
  1. 01

    Domain registered at Cloudflare (or transferred); DNS points apex + www to Vercel.

    step
  2. 02

    Cloudflare in front → handles WAF, bot blocking, page rules.

    step
  3. 03

    Static assets cached at the edge (300+ POPs).

    step
  4. 04

    Optional Worker layer: pre-Vercel routing, A/B tests, geo-redirects (EU users to eu.app.com etc.).

    step

Cases & edge cases

watch for these

DNS-only mode (gray cloud) when you DON'T want Cloudflare to proxy (e.g. specific subdomain → Vercel directly).

Page Rules → Cache Rules (the new system). Migrate before the old one sunsets.

R2 for user uploads has no egress fees — vs. S3 where bandwidth out is the bill.

Vendors & tools

what implements this

Cloudflare

primary

DNS + CDN + DDoS + edge compute.

pricingFree tier covers most early-stage needs.

04
DeployTest · Lint · Migrate

CI/CD (GitHub Actions)

GitHub Actions runs on every PR: lint, type-check, unit tests, e2e tests (Playwright), DB migration dry-run. Production deploys gate on the same workflow being green on main.

How it flows

step by step
  1. 01

    PR open → workflow runs: pnpm lint + typecheck + test + drizzle-kit dry-run.

    step
  2. 02

    Playwright e2e against the Vercel preview URL.

    step
  3. 03

    Merge to main → migration job runs first (against prod DB), then Vercel promotes.

    step
  4. 04

    On failure: deploy halts, channel notification, rollback link in the message.

    step

Cases & edge cases

watch for these

Run migrations BEFORE the app deploys; old code must work against the new schema.

Cache pnpm store + turbo cache → 5x faster CI.

OIDC for secrets (don't paste AWS keys into Actions secrets — use trust between Actions and your cloud).

Checklist

ship readiness
  • Migration runs before app deploy

    must
  • PRs blocked on red CI

    must
  • Cache (pnpm, turbo) configured

    should
  • OIDC for cloud credentials

    should

Where it lives

code references
References
  • .github/workflows/ci.yml
  • .github/workflows/migrate.yml
05
DeployPer-PR full stack

Preview Environments

Every PR gets its own URL, its own database (via Neon branching or Supabase preview projects), and a Stripe test environment. Reviewers can click and use the feature live.

How it flows

step by step
  1. 01

    PR opened → Neon branch created from prod schema (data-less).

    step
  2. 02

    Vercel preview deployed against the branch DSN.

    step
  3. 03

    Seed script runs (fixtures only — no real users).

    step
  4. 04

    Reviewer clicks the preview URL, exercises the change, leaves comments inline.

    step
  5. 05

    PR merged or closed → branch DB cleaned up after 7d idle.

    step

Cases & edge cases

watch for these

Don't seed real PII into previews — fake data only. GDPR issue otherwise.

Preview URLs need to be password-gated until publish (Vercel SSO or Cloudflare Access).

Long-lived previews ($$$) — auto-tear-down on PR close.

06
JobsInngest · Workflows

Background Jobs

Inngest for background work and cron. No Redis to manage, serverless-friendly, durable workflows with built-in retries. Triggers from Server Actions or external events; runs on Vercel serverless functions.

How it flows

step by step
  1. 01

    Define: inngest.createFunction({ id, trigger }, async ({ event, step }) => { ... }).

    step
  2. 02

    Server Action emits: await inngest.send({ name, data }).

    step
  3. 03

    Inngest delivers to your /api/inngest webhook → executes step-by-step.

    step
  4. 04

    step.run(name, fn) → automatic retry on throw, idempotency per step.

    step
  5. 05

    step.sleep, step.waitForEvent for long workflows.

    step

Cases & edge cases

watch for these

step.run is the unit of retry — chunk work into idempotent steps.

Inngest's dev server (npx inngest-cli@latest dev) → local UI for triggering / debugging.

Don't pass huge payloads in events — pass IDs and refetch.

Vendors & tools

what implements this

Inngest

primarysite

Serverless event-driven workflows + cron + retries.

Trigger.dev

alternate

Similar; better for AI workflows + long-running tasks.

BullMQ

alternate

Self-hosted Redis-based. Strong on Node servers; awkward on serverless.

Where it lives

code references
References
  • lib/inngest/client.ts
  • lib/inngest/functions/
07
OpsEnv vars · Rotation

Secrets Management

Secrets live in Vercel Environment Variables (per-env: dev/preview/prod), GitHub Actions secrets for CI. NEVER committed. Rotation: documented per secret, with a runbook.

How it flows

step by step
  1. 01

    Vercel env vars: STRIPE_SECRET_KEY, CLERK_SECRET_KEY, DATABASE_URL — separately per environment.

    step
  2. 02

    Local dev: .env.local (gitignored) loaded by Next.js automatically.

    step
  3. 03

    Pull: vercel env pull .env.local refreshes local from Vercel.

    step
  4. 04

    Rotation: change at vendor → update Vercel + re-deploy → confirm green → revoke old.

    step

Cases & edge cases

watch for these

Never log secrets — even partially. Pre-commit hook scans for likely tokens.

Database URL with the pool host (PgBouncer) for serverless; with the direct host for migrations.

Webhook signing secrets: NEVER reuse across environments (test endpoints get probed).

Checklist

ship readiness
  • Pre-commit secret scan (e.g. trufflehog)

    must
  • Per-environment env vars in Vercel

    must
  • Rotation runbook per critical secret

    should
Annotate0 strokes

Apple Pencil draws with pressure. Fingers still scroll. Saved per pillar.