
From Vercel to Cloudflare Workers: A Migration Retrospective.
Why we moved a production SaaS app off Vercel, the gotchas around Workers runtime APIs, and the latency and cost numbers that justified two weekends of engineering time.
Why we moved
The client's SaaS app was spending $1,800/month on Vercel Pro at a traffic level that should have been $400. The culprit was function invocation pricing on high-frequency API routes and egress costs on image responses that weren't being cached correctly. The numbers pointed clearly at Cloudflare Workers + R2 for assets.
What actually moved and what didn't
We moved the API layer - 14 edge functions - to Cloudflare Workers. Static assets and images moved to R2 with a Cloudflare cache rule covering 99% of requests. The Next.js frontend stayed on Vercel. This hybrid approach is underrated: Vercel's Next.js integration is genuinely best-in-class for the SSR/ISR use case.
The runtime gotchas nobody warns you about
Three things that cost us engineering time: Workers don't have Node.js crypto (rewrite to Web Crypto API), the Workers KV API is eventually consistent with up to 60-second stale reads (we moved session state to Durable Objects), and Workers have a 128MB memory limit per invocation (we redesigned filtering to the D1 database layer).
The numbers after migration
Monthly infrastructure cost: $1,800 on Vercel down to $210 on Cloudflare Workers + R2. API latency p50: 180ms vs 34ms (true edge, ~240 PoPs globally). API latency p99: 820ms vs 190ms. The cost saving alone justified the migration; the latency improvement was a bonus the client used in their next investor update.
When we'd recommend this move and when we wouldn't
Migrate to Workers if: your Vercel bill is dominated by function invocations, your users are globally distributed, and your API functions are stateless. Don't migrate if: your functions rely on Node.js-specific APIs, your team has no prior Workers exposure, or your traffic is primarily from one region where Vercel already performs well.