Skip to content

[Muse Spark] Hosting landscape 2026: stay on Netlify (Credit Pro) vs pivot — ranked recommendation + configs #1570

Description

@teetangh

Hosting landscape 2026: stay on Netlify (Credit Pro) vs pivot — ranked recommendation + configs

Filed by Muse Spark after parallel explore-agent research: (a) read-only audit of this repo's deploy stack, (b) triage of all platform/infra GitHub issues, (c) live web research on Netlify / Vercel / Cloudflare / Fly / Render / Railway / Cloud Run / ACA / SST+AWS pricing + fit as of 11 Sep 2026.
Scope per requester: India-first, 100s–1000s users now, scale to worldwide later. Concurrency + traffic-spike behaviour explicitly in scope. Netlify Legacy Pro → Credit Pro migration explicitly in scope. Configs included.


0. TL;DR + recommendation (phased stay-then-pivot)

Do NOT hard-pivot this week. Stay on Netlify short-term, fix 5 known-bad configs, make the app portable in parallel, and pivot to Fly.io (BOM/SIN) only when a numeric trigger fires.

Rank Platform Verdict for THIS stack Rough cost at our scale
Stay (0–3 mo) Netlify (resolve Legacy vs Credit below) Cheapest switch cost. Full Node, ISR/on-demand/PPR-via-function all work today. Pain is real (#1124 stall, #932 cross-region, #1560 cache) but all have mitigations that don't require re-platforming. $20/mo flat (+ credits if on Credit Pro). See §3 burn math.
1st pivot target Fly.io + Cloudflare CDN front + Supabase ap-south-1 + Upstash Best fit for Next.js App Router + Prisma + react-pdf + Razorpay + 5-min cron + India audience. Full Docker, no function timeout, persistent pool kills Supavisor pain, BOM region kills cross-region latency, cheapest persistent egress. ~$29–60/mo (2 machines + volume + egress).
2 Render Standard + Pro workspace Easiest team DX if you want native Cron + previews + autoscale without Docker ops. Same Node fidelity as Fly. ~$50–115/mo team before traffic.
3 SST (ECS/Fargate container, NOT Lambda) + AWS Best if AWS/compliance/VPC already in picture. EventBridge cron first-class, CloudFront ISR, Graviton savings. Overkill for single-service SaaS (ALB $22 + NAT $33/AZ floor, 8–12 min first deploy). ~$50–110/mo at scale.
4 Railway Pro Fastest solo iteration, per-second billing. Fine for standalone MVP. 2026 reliability reports weaker than Fly/Render. ~$15–40/mo.
5 Vercel Pro Best DX/ISR/PPR/previews/monorepo, maxDuration 800s, Fluid attachDatabasePool. Bill shock risk with react-pdf + 8.6k cron runs/mo + image/ISR. Per-seat kills seat economics vs Netlify flat $20. ~$60–400/mo for 3 seats moderate.
6 Cloud Run / Azure Container Apps Best enterprise serverless-container (scale-to-zero, 2M req + 360k GiB-s free, any timeout, native Scheduler). Heaviest ops (Registry → revision previews, LB/logging/egress separate). ~$0–82/mo spiky → grows linearly.
7 Cloudflare Workers + OpenNext Cheapest at scale, fastest edge (330 PoPs, India 10–30ms), zero egress. Blocker today: react-pdf / Prisma TCP / 10–50ms CPU / 128–256MB / Images all need rework. Re-evaluate after official Adapter API adapter + Containers GA. ~$5–25/mo if you fit. We don't yet.
Avoid (new) AWS Amplify / App Runner / ECS-classic Amplify: no on-demand ISR/streaming/edge-middleware, 220MB SSR cap. App Runner: closed to new customers 30 Apr 2026 → ECS Express instead.

Why phased, not hard pivot: re-platforming does NOT fix our top incidents (#1124 stall is Netlify-specific and goes away on Fly, but #1560 cache-key, #1436 pool=1 deadlock family, #1298 RESEND key, #1377 test-keys-in-prod, #920 build-hits-DB all move with us if we lift-and-shift). Fix-then-port is cheaper than port-then-debug.

Pivot triggers (any one fires → start Fly port, §8):

  1. #1124-class p95 TTFB on cold paths > 8s for 7 consecutive days after §6 stay-fixes, OR BetterStack #1557 false-down > 3/day.
  2. Credit-Pro burn > 2500 credits/mo for 2 consecutive months with BW > 120GB/mo (means PDFs/images must leave the function anyway).
  3. Scheduled ticker p99 > 20s or any reconcile-* needing > 30s (scheduled-function cap) more than weekly.
  4. Handler size hits 250MB deploy cliff (Stream: restore noise cancellation and background blur, and put a size budget on the server function #1158) and blocks a feature merge.

1. Context / constraints (what this ranking is optimised for)


2. What keeps breaking on Netlify (measured, linked)

2.1 One fat function + cold-stall (the #1 platform tax)

2.2 DB cross-region + PG_POOL_MAX=1 (the #2 tax, interacts with #1)

2.3 Caching / ISR footguns (safe alone, unsafe together)

2.4 Build / deploy / preview / env sync

2.5 Cron / scheduler (better than GA, still fragile)

2.6 Capacity / readiness umbrellas


3. Netlify Legacy Pro → Credit Pro: what actually changed (read this before clicking Migrate)

Sources (accessed 11 Sep 2026): netlify.com/pricing, docs.netlify.com/.../credit-based-pricing-plans, .../how-credits-work (2026-08-12), changelog 2026-04-14-pricing-updates-april-2026, changelog 2026-07-14-pro-plan-credit-tiers. Verify before procurement — all three frontend clouds repriced 2025–2026.

Legacy Pro (pre-4 Sep 2025) Credit Pro (new default)
Seat $19/member/mo incl. Git Contributors Flat $20/mo/team, unlimited seats (Apr 14 2026 change, retroactive next cycle)
Bandwidth ~1TB/mo then overage/package Metered 20 credits/GB from byte 1 (Apr 2026: 10→20)
Functions Billed by request count, fixed limits, 1GB fixed Billed GB-hr (10 credits, Apr 2026: 5→10), 1–4GB configurable + vCPU proportional
Builds Minutes (300→100 free cut 2025) + concurrent 15 credits/prod deploy, previews/branch 0, minutes NOT metered; extra concurrent build $40
Requests Per-request tiers 2 credits/10k (Apr 2026: 3→2, ~$0.01/10k)
Forms/Analytics Submission tiers / add-on Forms free unlimited, analytics by lookback (7d Personal/30d Pro)
Switch Irreversible, no transfer back to legacy team
Plans Pro legacy Free $0/300cr hard stop · Personal $9/1000cr (recharge 500/$5) · Pro $20/3000cr (recharge 1500/$10 = $0.00667/cr) · tiers 5000/$33, 10000/$63, 15000/$95, 20000/$126. Rollover 1mo only on ≥5000 tier.

3.1 Credit burn math for OUR workload (model, then measure)

Meters (Pro pack rate): deploy 15 · compute 10/GB-hr · BW 20/GB · requests 2/10k.

  • Deploys, not minutes. 2 prod deploys/day = 60 × 15 = 900 credits (30% of base) before traffic. Frequent Razorpay/webhook fix deploys hurt. Previews free — shift QA there (netlify.toml already skips Dependabot).
  • Bandwidth is ~2/3 of base. 150GB (react-pdf downloads + images if NOT offloaded to R2/S3) = 3000 credits alone. Never host PDFs/MP3/video on Netlify (use Supabase/R2), front with Cloudflare, daily BW watch (Billing Guardrails: Prevent Surprise Bills Across All Services (Vercel, Netlify, Supabase, Stream, etc.) #481 §2.2: $104.5K MP3 190TB/4d lesson).
  • Compute has no free tier. Sync 60s (good for >10s, tight for react-pdf 20–40s), scheduled 30s (risk if 5-min ticker does rollups > 30s), background 15min with 202 (fixes long PDF but needs async poll/webhook — extra requests+compute). 1GB default; 4GB for PDF quadruples burn. Example doc: 2.5GB×37min = 1.54 GB-hr = 15.4 credits.
  • Worked example: 100GB BW = 2000cr + 60 deploys = 900cr + 27 GB-hr compute (~500k×200ms @1gb) = 277cr = ~3177 > 3000 base → auto-recharge fires. At 100s–1000s users this is avoidable (offload PDFs/images, cut deploys, ISR more); at worldwide image-heavy scale it is not.
  • Single region (cmh default). Prisma to ap-south-1 adds 200ms+/query → longer GB-hr + need Supavisor 6543 + ?connection_limit=1. No multi-region functions.
  • ISR via adapter: time + on-demand supported, but via Function layer not edge-stitched. High revalidation rate = compute+BW+requests triple-count.
  • Stay on Legacy if: 1–2 seats + predictable ~1TB + low compute — switching is one-way. Move to Credit if: 3+ seats (seat savings dwarf usage delta) or you want hard caps (Auto-Recharge OFF → pause not bill; legacy has NO caps, only 50/75/90/100% email alerts).

Site plan evidence: #1482 API readout account teetangh/Practitionist-Deploys, Pro plan — does not state legacy vs credit. Action before any decision: confirm in Netlify dashboard → Team settings → Billing whether this team shows "Legacy Pro" or "Credit Pro / 3000 credits", and whether Auto-Recharge is ON/OFF.


4. Platform landscape (2026-09-11 list prices, USD)

4.1 Vercel Pro — best DX/ISR/PPR, worst seat economics for us

  • Base Pro $20/seat/mo incl. 1 deploy seat + $20 usage credit/seat. Viewers free. SSO $300, HIPAA $350, preview-suffix $100, Observability Plus $1.20/M.
  • Incl (per team): 1TB Fast Data Transfer + 10M Edge Requests. Then: FT $0.15/GB · Edge $2.00/M · Origin transfer $0.06/GB from byte 1 · Invocations $0.60/M from req 1 · Active CPU (Fluid, code-only, I/O free) $0.128/CPU-hr (BOM $0.14) · Provisioned mem $0.0106/GB-hr · Build $0.126/min.
  • Real bills (MakerKit 2026-05): 3 seats + 250k visitors/5M API ≈ $305/mo ($78 BW + $130 edge + $63 builds). 1.5M/10TB ≈ $3,096/mo. BW + edge dominate, not seats/CPU.
  • Fit: only true edge-stitched PPR, flawless revalidateTag, maxDuration 300s default / 800s max / 1800s beta solves >10s, Fluid attachDatabasePool solves leaks, best previews/monorepo/after(). Watch per-seat + zero-free compute + image/ISR +10–30%.

4.2 Cloudflare Workers + OpenNext — cheapest/fastest edge, blocked for this stack today

  • Direction 2026: new → Workers + @opennextjs/cloudflare (GA Feb 2026) or vinext for Next 16. next-on-pages maintenance. Docs 2026-08-25 list vinext recommended.
  • Pricing: Free $0 (500 builds, 1 concurrent, 100k req/day, 10ms CPU, 3MB gzip) · Pro $20/account (not/seat; 5000 builds, 5 concurrent, 50ms CPU, 15MB gzip) · Workers Paid $5 incl 10M req then $0.30/M. Zero egress. KV/R2/D1 separate. Images $5/100k stored + $1/100k transforms.
  • Blockers: 10ms free / 50ms paid is CPU (not wall). Prisma + react-pdf + JWT easily exceed → 1101. Mem 128MB free / 256MB paid. runtime="edge" must go for OpenNext. next/image needs Images binding. ISR needs R2 + r2IncrementalCache else SSR. Native modules (sharp/canvas) fail.

4.3 SST v3 (Ion) + AWS — most portable serverless, heaviest ops

  • SST $0 MIT (Pulumi). sst.aws.Nextjs → Lambda+CloudFront+S3+Dynamo(ISR)+SQS(reval). Alt sst.aws.Service → ECS Fargate next start standalone.
  • Raw AWS us-east-1: Lambda $0.20/M + GB-s, CloudFront $0.085/GB first 10TB, S3 $0.023/GB-mo, Dynamo/SQS pennies.
  • Worked: 5k users/500k views ~$49/mo (Lambda $5 + CF $12 + S3 $3 + Aurora Serverless $15 + ElastiCache $13 + R53 $1). 5M req ISR: Vercel $300–700 vs SST $55–110 vs CF $10–25 vs Hetzner $8–15.
  • Amplify Hosting: builds $0.01/min (1k free), storage $0.023/GB (5GB free), transfer $0.15/GB (15GB free), SSR $0.30/M (500k free) + $0.20/GB-hr (100 free). Examples 300 DAU $8.08 / 10k DAU+440GB $65.98. Limits: no on-demand ISR, no streaming, no edge middleware, 220MB SSR cap — avoid for new.
  • Watch: 8–12 min first deploy, 2–5 min iterates, CloudWatch DX, OpenNext lags Next releases weeks, ALB/NAT $90/env floor, Graviton arm64 −20%.

4.4 Fly.io — best fit default for us

  • No plans (Hobby/Launch/Scale retired Oct 2024). Support from $29 optional.
  • shared-cpu-1x 256MB $2.02 / 1GB $5.92 / 2x/1GB $6.64 / perf-1x/2GB $32.19. Extra RAM ~$5/GB. Per-sec, stopped rootfs $0.15/GB. Volumes $0.15/GB, snapshots $0.08/GB (10GB free). Dedicated IPv4 $2, wildcard $1.
  • Egress NA/EU $0.02 / APAC/SA $0.04 / Africa/India $0.12 — no free allowance new orgs. 7.5× cheaper than Render $0.15 in NA/EU, 6× spread hurts multi-region India (still cheaper than Netlify $0.133/Vercel $0.15 at our volumes).
  • Reservation −40% ($36/yr for $5/mo shared). Real SaaS 2 machines+PG+Redis ~$29/mo, 3-region perf ~$226/mo.
  • Fit: full Node (react-pdf fine), no timeout, persistent pool (10 conns, skip Supavisor latency if single-region; keep Supavisor if scaled), any region incl. BOM/SIN near Supabase, PR machines, fly deploy + fly logs.

4.5 Render — easiest team DX

  • Workspace (Apr 23 2026 seats removed): Hobby $0 (1 member, 25 svcs, 5GB BW, 500 build-min) · Pro $25/mo flat unlimited seats (25GB BW, autoscale, previews) · Scale $499 (1TB, SSO).
  • Compute/sec: Starter $7 (0.5/512MB) · Standard $25 (1/2GB) · Pro $85 (2/4GB) → Ultra $450 (8/32GB). BW overage $0.15/GB, builds 1k free then $5/1k-min, disks $0.25/GB, KV $10/256MB–$32/1GB, PG $6–$19.
  • Floor: Starter $7 + PG $6 = $13 solo; Pro ws + Standard + PG Pro + KV = $115 team before traffic. Native Cron Jobs, full-stack previews, private networking. Single region (pick Singapore for India), rolling deploys need config.

4.6 Railway — fastest solo iteration

  • Trial $5 once/30d · Hobby $5 incl $5 · Pro $20 incl $20 · Enterprise custom. Credit resets, no rollover. Rates RAM $10/GB + vCPU $20/vCPU + egress $0.05/GB + vol $0.15/GB, per-sec, stopped $0. 1vCPU+2GB always-on = $40 → Hobby bill $40, Pro bill $40 ($20 covered). Tiny standalone (0.5/512MB) ~$15/mo. PR envs, cron, Dockerfile. 2026 reliability/storage reports weaker; 1-region; front with CF if India-heavy.

4.7 GCP Cloud Run / Azure Container Apps / AWS ECS-Fargate — enterprise serverless containers

  • Cloud Run: request-based (scale-to-zero) CPU active $0.000024/vCPU-s ($0.086/hr) + mem $0.0000025/GiB-s + req $0.40/M. Free 2M req + 180k vCPU-s + 360k GiB-s. Instance-based (min-instances) CPU $0.000018/s + mem $0.000002/s (no req fee). Example 10M×400ms×1vCPU/512MB/20 conc EU ≈ $81.72/mo after free. Tier1 vs Tier2 regions, Registry+Build+Logging+LB+egress separate.
  • ACA Consumption: per-sec vCPU+GiB+req. Free/grant per sub/mo 180k vCPU-s + 360k GiB-s + 2M req. Active vs idle (<0.01 CPU + <1KB/s) discounted. Scale-to-zero $0.
  • Fargate us-east-1 x86: $0.04048/vCPU-hr + $0.004445/GB-hr, ARM −20%, 1-min min, per-sec. Spot −70% ($0.01291). 0.25/0.5GB ~$9/mo, 4/16GB ~$145/mo. Real ECS overhead ALB $22 + NAT $33/AZ + logs/transfer ~$90/env fixed before tasks. 8 svc×0.5/1GB = $144/mo 24/7.
  • App Runner: no new customers after 30 Apr 2026 — use ECS Express. Do not choose.

4.8 Concurrency + traffic-spike cheat sheet (what breaks first at 2× peak)

Platform Concurrent cap Timeout Spike behaviour What to set
Netlify Pro (today) 125/site Sync 26s measured (docs 60s — confirm on Credit Pro) / Scheduled 30s / Background 15m Burst creates cold instances → #1124 24–39s stall → 504s + false-down #1557. No queue. ISR more, ?limit small bites, ticker 6s timeouts, retry past stall, keep-warm only single-click
Vercel Pro Fluid 1000+ (soft) 300s default, 800s max, 1800s beta Fluid suspends idle, needs attachDatabasePool else leaks. Best burst absorb + Skew Protection. maxDuration, spend caps, Pause, Attack Challenge, WAF
Fly Machine concurrency (soft+hard limit) + autoscale count None (machine) Queues at proxy, scales machines in ~300ms–2s. Predictable. soft_limit/hard_limit, min_machines_running=1, auto_stop, reservation
Render Autoscale count + per-service concurrency 60–100s tunable Rolling deploys need config else brief 502. Private networking helps pool. Autoscale CPU/mem target, healthcheck /api/health, zero-downtime rolling
Cloud Run/ACA 1000/instance (tunable 1–1000) + max-instances Up to 60m / none Scale-to-zero cold ~500ms–2s, then linear. Best spiky cost. concurrency, min-instances=1 for checkout/webhook, max-instances cap = cost cap
SST Lambda 1000/account/region (burst) 15m Throttles → retry + DLQ + SQS. Fargate alt has no timeout. Reserved concurrency for webhooks, DLQ on Razorpay route
CF Workers 1000s (isolate) 10–50ms CPU / ~30s wall Instant, but CPU-kills long tasks. Move react-pdf/Prisma to Queue + R2 + D1/Hyperdrive

Vendor cliffs bind BEFORE infra at our current scale: Stream 100 MAU, Resend 100/d, Novu 30k/mo, Upstash 10k/d (all ~$10–20/mo to lift per #874). Caching absence moves wall 2–3k→10k (#734 highest leverage). 125+60 moves to 10k (Pro+Supabase bump). 100k needs workers/replicas/queue.


5. Feature-fit matrix (for THIS stack)

Capability Vercel Pro Netlify Credit Pro CF Workers/OpenNext SST+AWS Fly Render/Railway Cloud Run/ACA/ECS
ISR time-based ✅ Native sub-sec ✅ Via adapter, occasional stale ✅ Via R2/KV, eventual ~60s ✅ Native (Dynamo/SQS) / ✅ Node ✅ Just Node + CDN headers ✅ Same ✅ Same
ISR on-demand (revalidateTag/Path) ✅ Full ✅ Supported 🟡 Maturing ✅ Yes (SST), ❌ Amplify ✅ Yes ✅ Yes ✅ Yes
PPR / use cache ✅ Only true edge-stitched ✅ Via Function (functional, perf gap) 🟡 Maturing, Adapter API 16.2 🟡 Depends ✅ Just Node ✅ Just Node ✅ Just Node
>10s functions ✅ 300–1800s ✅ Sync 60s, Bg 15m (background:true), Sched 30s ❌ 50ms CPU — no for react-pdf ✅ Lambda 15m / Fargate none ✅ None ✅ None (60–100s tunable) ✅ 60m / none
react-pdf (Node/sharp/canvas/bundle) ✅ 4GB, 250MB (5GB large) ✅ 4GB, 6MB buffered/20MB streamed ❌ Native fails, Images add-on ✅ Lambda+Sharp layer / Fargate best ✅ Full Docker ✅ Full Docker ✅ Full Docker
Cron 5-min ticker (~8640/mo) ✅ Vercel Cron sec-precision ⚠️ Scheduled 30s/256KB ✅ Cron Triggers + Queues ✅ EventBridge in sst.config ⚠️ Separate machine + superfly/cron or external ✅ Native Cron (Render) / Cron (Railway) ✅ Scheduler/Logic/EventBridge
Razorpay webhooks (raw body, idempotent) force-dynamic + after()/waitUntil ✅ Bg 202 + retry 1m/2m, careful body parse ⚠️ Streaming/signing quirks, tail logs ✅ API GW raw + DLQ ✅ Stable anycast + volume replay ✅ Stable URL + disk ✅ Stable + VNet + DLQ
Prisma + Supabase pooling 6543 + directUrl 5432 + attachDatabasePool ⚠️ Single-region, connection_limit=1, no Fluid helper ⚠️ TCP needs Hyperdrive, prefer HTTP/Data API ✅ VPC + RDS Proxy/Supavisor, warm control ✅ Long-lived pool (10, no pooler) + Supavisor if scaled ✅ Same long-lived ✅ Same + private link
Preview envs ✅ Best (PR URL, Skew, comments) ✅ Free previews/branch, instant rollback ✅ Branch previews / opennext preview ⚠️ DIY (--stage pr-123 + GH) ✅ PR machines + volumes ✅ Full-stack previews (Pro) / PR envs ⚠️ DIY (revisions + GH)
Monorepo ✅ Turbo cache, root settings ✅ 3+ concurrent, shared env, per-app adapter ⚠️ Turbo pain, npm workspaces advised ✅ Multi-component sst.config ✅ Multi-process fly.toml ✅ Monorepo + private net ✅ ACR + pipelines
Lock-in Highest (Fluid/after/Blob/KV/Image/WAF/Skew) Medium, improving (OpenNext adapter mid-2026) Runtime (V8+KV/R2/D1/Queues/Hyperdrive) Most portable serverless (CF/Lambda/S3/Dynamo/SQS) Highest portability (Dockerfile+standalone) Same Same

Pooling notes: runtime DATABASE_URL=…pooler…:6543 + DIRECT_URL=db…:5432 migrations. Disable prepared statements (pgbouncer=true or prepare:false) unless PgBouncer ≥1.21 server-side. Supabase 6543 = txn-only since 28 Feb 2025, 5432 = session. Vercel Fluid MUST attachDatabasePool else suspended leaks. Containers with 1 always-on Node can use direct + small in-process pool and skip Supavisor latency (+2ms/query, −50% throughput vs co-located PgBouncer). Redis: none include managed Redis for this pattern — bring Upstash/Redis Cloud (edge) or ElastiCache/Memorystore. Stream.io outbound HTTPS only — any platform works; pin region near Supabase to cut tail. India: CF 348 PoPs wins TTFB (35–48ms São Paulo vs Vercel 120–145ms; India 10–30ms vs 40–80ms benchmarks) but loses on react-pdf/Prisma — pair CF CDN in front of Fly/BOM or SST ap-south-1 if audience India.
2026 equalizer: Next 16.2 Deployment Adapter API (stable Mar 2026) — Netlify/CF/AWS building official adapters on same contract. Code written to OpenNext today survives transition.


6. Stay path: 5 fixes + guardrails (do these even if we pivot — they move with us)

  1. Netlify Durable Cache ignores the query string on /api/user/consultants: page 2 serves page 1 for 60 s in production #1560 — vary cache by real query params (P-high, 1-line-class fix). Either (a) Netlify-Vary: query=page|limit|sort|domain|minRating|minPrice|maxPrice|companies|search|languages on /api/user/consultants (+ rating|consultantId|search on /api/user/reviews), or (b) smallest/cannot-be-wrong: CDN-cache only default page else private,no-store. Grep all 10+ public,s-maxage routes before merge.
    // app/api/user/consultants/route.ts — option (a)
    res.headers.set("Netlify-Vary", "query=page|limit|sort|domain|minRating|minPrice|maxPrice|companies|search|languages");
    // option (b) — non-default query:
    // res.headers.set("Cache-Control", "private, no-store");
  2. /api/health pages ~8×/day on Netlify cold-instance stalls, and reports the database unreachable on every one of them #1557 — stop health false-downs. Retry DB probe once after stall (lib/prisma.ts connects in ~330ms on retry), don't arm timers before stall, separate liveness (200 if loop alive) from readiness (DB check with retry + cache-status header). Loosen BetterStack to 45s timeout + 5m confirm, or probe / + /api/health composite.
  3. Make build-time-DB pages dynamic to remove the prerender DB connect (drop the #919 phase-timeout workaround) #920 + [billing][P2 MEDIUM] Four B2B invoice call sites read SUPPLIER_STATE_CODE from env without consulting the GSTIN, unlike the B2C mint #1447 + Audit what console.error/warn payloads serialise, now that they reach Netlify function logs #1127 — build/env hygiene. force-dynamic audit on app/explore/* DB pages so build never opens DB; route all 4 B2B sites through resolveSupplierStateCode (GSTIN first, env fallback, disagree fail-closed); PII sweep on 709 log sites, prefer reportSentryError/Sentry.logger.
  4. [reconcile][P2 MEDIUM] POST /api/admin/reconcile-ledgers runs ~27 s on the shared dataset and the Netlify edge answers 504 while the report row still lands #1454 + ticker caps — respect 26s/30s ceilings. ?limit/scope on reconcile-ledgers like cleanup twins, full scope only from scheduled job, admin enqueue-and-poll; keep PER_TARGET_TIMEOUT_MS=6000 (cron-tick.mts:50), abandoned-payments limit 10 ([enterprise][P0 CRITICAL] walletCredit increments a NULL walletBalance, so the cached balance stays NULL while the ledger is credited (ledger-vs-cache drift on any account created without a zero balance) #1459).
  5. Stream: restore noise cancellation and background blur, and put a size budget on the server function #1158 + Sentry observability: current landscape + follow-ups #900 + Billing Guardrails: Prevent Surprise Bills Across All Services (Vercel, Netlify, Supabase, Stream, etc.) #481 — budgets + guardrails. CI netlify build; du -sh .netlify/functions-internal/___netlify-server-handler (fail > 220MB); Sentry prod sampling 0.1, sendDefaultPii:false, env-driven DSN, delete /sentry-example-*; Auto-Recharge OFF (hard cap = pause not bill), per-context env (fix Deploy previews never report to Sentry, and the join toast claims they do #1086/Set Razorpay LIVE keys on production and delete RAZORPAY_ALLOW_TEST_KEYS_IN_PRODUCTION before signup reopens #1377/P0: production email delivery dead since 2026-06-18 — invalid RESEND_API_KEY hard-locks signup and password reset #1298 ordering: KYC→live Razorpay keys prod-only→unset opt-out→webhook secret→redeploy→rotate Resend), offload PDFs/images to R2/S3 (never Netlify BW), take:100 + select>include + index advisor per Billing Guardrails: Prevent Surprise Bills Across All Services (Vercel, Netlify, Supabase, Stream, etc.) #481 §13–16 + emergency runbook §15.

Stay-config patch (copy-paste):

# netlify.toml — stay path (append; do NOT re-add memory block per #1124 comment)
[functions."___netlify-server-handler"]
  node_bundler = "esbuild"
  # memory intentionally 1024 — 2048 measured dead (#1124, 08b10ce4)

[[headers]]
  for = "/api/user/consultants"
  [headers.values]
    Netlify-Vary = "query=page|limit|sort|domain|minRating|minPrice|maxPrice|companies|search|languages"
[[headers]]
  for = "/api/user/reviews"
  [headers.values]
    Netlify-Vary = "query=rating|consultantId|search"

7. Pivot-ready configs (no re-platform without these passing on preview)

7.1 Fly.io (1st pivot target) — fly.toml + Dockerfile

# fly.toml — India-first: BOM primary, SIN backup
app = "familiarise-web"
primary_region = "bom"

[build]
  dockerfile = "Dockerfile.prod"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]
  [http_service.concurrency]
    type = "requests"
    soft_limit = 100
    hard_limit = 250
  [[http_service.checks]]
    interval = "30s"
    timeout = "5s"
    grace_period = "10s"
    method = "GET"
    path = "/api/health"

[[vm]]
  size = "shared-cpu-1x"
  memory = "1gb"
  # bump to 2gb when react-pdf P95 > 800MB RSS

[env]
  NODE_ENV = "production"
  PG_POOL_MAX = "10"
  # DATABASE_URL = direct :5432 ok single-region; keep :6543 Supavisor once >2 machines
# Dockerfile.prod already exists — ensure:
# FROM node:22-slim, output:standalone, NEXT_PUBLIC_* baked per-env, HEALTHCHECK /api/health
# CMD ["node", "server.js"]

Cron on Fly: separate process = "cron" running tsx jobs/ via superfly/cron, OR keep GH Actions backstop + Upstash QStash for Class-A (#1010). Front with Cloudflare DNS/CDN (10–30ms India) + R2 for PDFs/images (#1314).

7.2 Render (easiest team) — render.yaml

services:
  - type: web
    name: familiarise-web
    runtime: docker
    dockerfilePath: ./Dockerfile.prod
    plan: standard # 1 CPU / 2GB
    region: singapore
    healthCheckPath: /api/health
    autoDeploy: true
    envVars:
      - key: NODE_ENV
        value: production
      - key: PG_POOL_MAX
        value: 10
    scaling:
      minInstances: 1
      maxInstances: 3
      targetCPUPercent: 70
  - type: cron
    name: cron-tick
    runtime: docker
    schedule: "*/5 * * * *"
    command: "npx tsx jobs/cron-tick.ts"

7.3 SST ECS/Fargate (if AWS) — sst.config.ts sketch

// sst.config.ts — container, not Lambda (avoids 250MB + 15m caps for react-pdf)
new sst.aws.Service("Web", {
  cluster: "familiarise",
  image: { dockerfile: "Dockerfile.prod" },
  cpu: "1",
  memory: "2 GB",
  scaling: { min: 1, max: 4, cpu: 70 },
  loadBalancer: { ports: [{ listen: "443/https", forward: "3000/http" }] },
});
// EventBridge cron replaces cron-tick.mts:
// new sst.aws.Cron("Tick", { schedule: "rate(5 minutes)", job: "jobs/cron-tick.ts" });

7.4 Vercel (if ISR/PPR becomes core) — minimal diff

// app/api/admin/reconcile-ledgers/route.ts
export const maxDuration = 300; // 800 max, 1800 beta
// lib/prisma.ts — Fluid: import { attachDatabasePool } from "@vercel/functions";
// attachDatabasePool({ connectionString: process.env.DATABASE_URL });

Plus Spend Management $100 + Pause, Attack Challenge, WAF bots, ignoreCommand, offload PDFs to background/Fargate.

7.5 Cloudflare front (works with ANY stay/pivot — do first)

DNS → Cloudflare, cache /_next/static/* + public/* immutable, bypass /api/* except allow-listed s-maxage routes WITH Netlify-Vary/CDN-Cache-Control fixed per #1560. This alone cuts BW credits (Credit Pro) / FT $$ (Vercel) regardless of origin.


8. Decision runbook: measure → trigger → migrate

  1. This week (stay): confirm Billing shows Legacy vs Credit + Auto-Recharge; land §6 (1)–(5); add handler-size CI gate; set daily BW + credit alerts (Billing Guardrails: Prevent Surprise Bills Across All Services (Vercel, Netlify, Supabase, Stream, etc.) #481 §14); run chaos scenario 6 at 2× peak (Capacity estimation & load-test go/no-go: concurrent→DAU→MAU model, binding ceilings, vendor-tier blow-ups #874 go/no-go).
  2. Measure 2–4 weeks: p95 TTFB cold vs warm, BetterStack false-down/d, credit burn/wk + BW GB/wk, ticker p99 + 504 rate, deploy count/wk, handler MB, Supavisor EAUTHTIMEOUT/wk.
  3. Trigger (any §0 trigger): spin Fly bom preview (Dockerfile.prod + fly.toml §7.1), replay E2E + Razorpay webhook replay + reconcile-ledgers full-scope (must pass >30s case that Netlify can't), load-test 2× peak, compare p95 + $/mo with REAL BW.
  4. Cutover: CF DNS weighted → Fly 10% → 50% → 100%, keep Netlify preview + GH Actions backstop 1 week, then downgrade Netlify to Personal/Free for previews/rollback.
  5. Worldwide later: add sin/iad Fly regions + read-replica (or Accelerate infra: evaluate Prisma Accelerate (ap-south-1 pool) as a durable cross-region fix — relates to #932 #937) + R2 multi-region; re-evaluate Vercel/Cloud Run when PPR/edge-SSR dominates.

9. Open data needed (comment to unblock precise $/mo)


10. Sources (all accessed 11 Sep 2026 — re-verify before procurement)

Netlify pricing / credit plans / how-credits-work / Apr-2026 repricing / Jul-2026 Pro tiers · Vercel pricing / Pro plan / Functions usage / MakerKit May-2026 / AboveAPI Apr-2026 · Cloudflare OpenNext blog Apr-2025 / Workers Next.js docs Aug-2026 / Pages pricing Sep-2026 / Toolchew Jun-2026 · SST AWS Next.js Feb-2026 / Brandrums Jun-2026 / Starterpick Mar-2026 / SocialAnimal Apr-2026 · Fly pricing docs / AboveAPI Jun-2026 / Budgetforge Jul-2026 · Render pricing / workspace-plans Apr-2026 / Budgetforge Jul-2026 · Railway pricing/docs/plans · Cloud Run pricing / billing-settings / CloudCostKit · ACA pricing / billing Dec-2025 · Fargate/ECS pricing / Fortem May-2026 · ISR/PPR DevStacked Jun-2026 / SocialAnimal Apr-2026 · Vercel durations Aug-2026 / 30-min changelog Jun-2026 · Pooling Dusko Jul-2026 / Vercel KB Nov-2025.
Repo evidence: netlify.toml, netlify/functions/cron-tick.mts, lib/prisma.ts:11-68, next.config.mjs, middleware.ts, ADR-27, .claude/skills/nextjs-netlify-caching/SKILL.md, docs/perf/netlify-stall-ticket-draft.md.
Issues: #407 #459 #450 #481 #484 #639 #697 #705 #709 #734 #866 #874 #900 #907 #908 #920 #932 #937 #1010 #1066 #1086 #1117 #1119 #1120 #1124 #1127 #1158 #1160 #1275 #1298 #1314 #1341 #1377 #1413 #1436 #1441 #1443 #1446 #1447 #1449 #1450 #1454 #1456 #1468 #1476 #1482 #1487 #1506 #1517 #1530 #1557 #1560.

/cc @teetangh — needs your Billing screenshot + §9 numbers to lock Legacy-vs-Credit call. Proposed labels: infrastructure, performance, production-readiness.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    infrastructureInfrastructure, deployment, and DevOpsperformancePerformance improvements and optimizationsproduction-readinessPre-launch hardening and deployment readiness

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions