Vercel to Cloudflare Pages Migration Proposal
Date: January 2026
Project: Piston Labs React Application (Shop & Consumer Dashboards)
Current Stack: Next.js 15 + Supabase + Vercel
Target Stack: Next.js 15 + Supabase + Cloudflare Pages
Executive Summary
This document outlines the migration strategy from Vercel to Cloudflare Pages for the Piston Labs React application. The migration is feasible but requires careful handling of long-running API routes and some code adjustments for Cloudflare's runtime environment.
Recommendation: Proceed with migration using a phased approach, offloading heavy compute tasks to Cloudflare Workers with Queues.
Current Architecture Analysis
Tech Stack
| Component | Technology | Version |
|---|---|---|
| Framework | Next.js | 15.1.9 |
| React | React | 19.2.1 |
| Database | Supabase (PostgreSQL) | Latest |
| Auth | Supabase Auth (SSR) | @supabase/ssr 0.5.2 |
| Styling | Tailwind CSS | 3.4.17 |
| Runtime | Node.js | >= 20.0.0 |
External Services (Unchanged by Migration)
- Supabase - Database, Auth, Storage (keeping)
- OpenAI - GPT-4o-mini for document parsing
- Google Document AI - OCR processing
- OneSignal - Push notifications, Email, SMS
- TekMetric - Shop management webhooks
- AutoPi - Vehicle telemetry
API Routes Inventory (14 Routes)
| Route | Complexity | Timeout Needed | Migration Risk |
|---|---|---|---|
/api/pdf-parse | High | 5 minutes | High |
/api/webhooks/tekmetric | Medium | 30s | Low |
/api/webhooks/iot-device | Medium | 30s | Low |
/api/notifications/send | Medium | 30s | Low |
/api/autopi/sync | Medium | 30s | Low |
/api/device-onboarding/* | Low | 10s | Low |
/api/parsed-service-records/* | Low | 10s | Low |
/api/pdf-upload-sessions/* | Low | 10s | Low |
/api/push-notifications/* | Low | 10s | Low |
/api/internal/* | Low | 10s | Low |
/api/test-ocr-parse | Low | 30s | Low |
Cloudflare Pages Capabilities
What Cloudflare Pages Supports
| Feature | Support | Notes |
|---|---|---|
| Next.js 15 App Router | Yes | Via @cloudflare/next-on-pages |
| React 19 | Yes | Fully supported |
| API Routes | Yes | Converted to Cloudflare Workers |
| Middleware | Yes | Runs at the edge |
| Server Components | Yes | Supported |
| Static Generation | Yes | Supported |
| ISR | Limited | Different implementation |
| Edge Runtime | Yes | Native |
| Node.js Runtime | Compat | Via nodejs_compat flag |
Cloudflare Workers Limits
| Limit | Free Plan | Paid Plan ($5/mo) |
|---|---|---|
| CPU Time | 10ms | 30s |
| Duration | 30s | 5 minutes (with Unbound) |
| Memory | 128 MB | 128 MB |
| Subrequest | 50 | 1000 |
| Environment Variables | 64 | 64 |
| Script Size | 1 MB | 10 MB |
Critical: The pdf-parse route requires up to 5 minutes. This requires:
- Cloudflare Workers Paid plan ($5/mo)
- Workers Unbound pricing model
- Or: Offload to separate async processing
Vercel-Specific Code to Migrate
1. Route Segment Configs
Current (Vercel):
// app/api/pdf-parse/route.ts
export const maxDuration = 300 // 5 minutes
export const dynamic = 'force-dynamic'
export const runtime = 'nodejs'
Target (Cloudflare):
// app/api/pdf-parse/route.ts
export const runtime = 'edge' // or 'nodejs' with nodejs_compat
// For long-running tasks, use Cloudflare Queues
// See "Heavy Compute Strategy" below
2. Middleware (Supabase Auth)
Current: Works with Next.js middleware + Supabase SSR
Migration: Generally compatible. Update to use Cloudflare's request context.
3. Server-Side Supabase Client
Current:
import { cookies } from 'next/headers'
Migration: Works on Cloudflare Pages with @cloudflare/next-on-pages
4. Environment Variables
Current: Set in Vercel dashboard
Migration: Set in Cloudflare Pages dashboard or wrangler.toml
Required env vars:
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
OPENAI_API_KEY
GOOGLE_CLOUD_PROJECT_ID
GOOGLE_DOCUMENT_AI_PROCESSOR_ID
GOOGLE_CLOUD_CREDENTIALS (base64)
ONESIGNAL_APP_ID
ONESIGNAL_REST_API_KEY
TEKMETRIC_API_KEY
AUTOPI_API_KEY
CRON_SECRET
INTERNAL_ACCESS_USER_IDS
Heavy Compute Strategy: PDF Processing
The /api/pdf-parse route is the main challenge:
- Google Document AI OCR (network I/O)
- OpenAI GPT-4o parsing (network I/O)
- File upload to Supabase Storage
- Database writes
Option A: Workers Unbound (Recommended)
Keep the existing architecture but use Cloudflare Workers Unbound pricing:
- Cost: ~$12.50/million requests + $0.02/million ms
- Duration: Up to 5 minutes per request
- Complexity: Low - minimal code changes
# wrangler.toml
[build]
command = "npx @cloudflare/next-on-pages"
[[routes]]
pattern = "/api/pdf-parse"
worker = "pdf-processor"
[workers.pdf-processor]
compatibility_flags = ["nodejs_compat"]
Option B: Queue-Based Processing (More Scalable)
Split into async processing:
- Upload Handler (fast, edge):
- Accept file upload
- Store in Supabase Storage
- Queue processing job
- Return immediately
- Queue Consumer (background worker):
- Process OCR with Document AI
- Parse with OpenAI
- Update database
- Notify via webhook/WebSocket
User Upload → Edge Worker → Supabase Storage
↓
Cloudflare Queue
↓
Background Worker (5 min limit)
↓
Supabase DB + Webhook
Advantages:
- Better user experience (instant upload response)
- More reliable (retries built-in)
- Scales better
Migration Steps
Phase 1: Setup (Day 1)
- Create Cloudflare account / project
- Install
@cloudflare/next-on-pages - Add
wrangler.tomlconfiguration - Test local build with Wrangler
npm install @cloudflare/next-on-pages
npx wrangler login
Phase 2: Code Adjustments (Days 2-3)
- Update route configs for Cloudflare compatibility
- Add
nodejs_compatflag where needed - Test all API routes locally
- Implement queue-based PDF processing (if Option B)
Phase 3: Environment & Secrets (Day 4)
- Configure all env vars in Cloudflare dashboard
- Set up Google Cloud credentials (may need adjustment)
- Verify Supabase connectivity from Cloudflare edge
Phase 4: Testing (Days 5-7)
- Deploy to Cloudflare Pages preview
- Test all user flows:
- User authentication (sign in/out)
- Shop dashboard access
- Consumer dashboard access
- PDF upload and parsing
- Webhook reception
- Push notifications
- TekMetric integration
Phase 5: DNS & Cutover (Day 8)
- Configure custom domain in Cloudflare
- Update DNS records
- Monitor for 24 hours
- Decommission Vercel project
Cost Comparison
Current (Vercel)
| Item | Cost |
|---|---|
| Pro Plan | $20/user/month |
| Serverless Functions | Included (limited) |
| Bandwidth | 1TB included |
| Build Minutes | 6000/month |
Projected (Cloudflare Pages)
| Item | Cost |
|---|---|
| Pages | Free (or $5/mo for 5M requests) |
| Workers Unbound | ~$5/mo base + usage |
| Queues (if used) | $0.40/million messages |
| R2 Storage (optional) | $0.015/GB/month |
Estimated Savings: $10-15/month depending on usage
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| PDF processing timeout | Medium | High | Use Workers Unbound or Queues |
| Supabase SSR incompatibility | Low | High | Test thoroughly; fallback available |
| Google Cloud auth issues | Medium | Medium | Use JSON credentials in env var |
| Webhook timing issues | Low | Low | Workers handle webhooks well |
| Cold start latency | Medium | Low | Edge deployment minimizes this |
Rollback Plan
If critical issues arise:
- Keep Vercel project active (don't delete)
- Switch DNS back to Vercel
- Full rollback in < 5 minutes
Recommendation
Proceed with migration using Option A (Workers Unbound) for initial release:
- Minimal code changes
- Maintains existing architecture
- Cost-effective ($5-10/month total)
- Can upgrade to queue-based (Option B) later if scale demands
Timeline: 8 working days for full migration
Prerequisites:
- Cloudflare account with Workers Unbound enabled
- All environment variables documented and ready
- Test environment for validation
Next Steps
- Tyler approval of migration approach
- Set up Cloudflare account and project
- Create feature branch:
feature/cloudflare-migration - Begin Phase 1 implementation
Document prepared by phil agent - January 2026