Build on tech that can be moved anywhere
Vendor lock-in isn't just a technical problem — it's a cost problem. When you can't leave, you can't negotiate. Here's what locks you in and how to stay portable.
What locks you into Vercel
Vercel's DX is excellent — that's by design. But several features create hard dependencies: @vercel/analytics and @vercel/speed-insights add tracking that only works on Vercel. Edge Middleware uses Vercel's edge runtime — try deploying it to Cloudflare or AWS and you'll be rewriting.
Vercel KV, Blob, and Postgres are Vercel-hosted services with Vercel-specific SDKs. next/image with the default loader requires Vercel's image optimization service. ISR with on-demand revalidation uses Vercel's infrastructure. None of these are bad features.
But each one is an anchor that makes migration harder and more expensive.
What stays portable
The good news: most of your application logic is already portable. React components, TypeScript business logic, and CSS work everywhere. Static export (output: 'export') produces plain HTML/JS/CSS that can be deployed to any CDN or static host — Cloudflare Pages, Netlify, S3, GitHub Pages, literally any web server.
API routes using standard Web APIs (Request/Response) can move to Cloudflare Workers, Deno Deploy, or any Node.js server with minimal changes. Database queries through standard ORMs (Prisma, Drizzle) work with any compatible database, not just Vercel Postgres.
The escape plan
Before you need to migrate, have a plan: Keep business logic in a vendor-neutral layer. Your calculation functions, data transformations, and validation should import zero platform-specific packages. Use environment variables as the single source of truth for configuration.
Switching a database URL is trivial; refactoring hardcoded Vercel KV calls is not. Avoid @vercel/* packages in production dependencies. For analytics, use Plausible, Umami, or Cloudflare Web Analytics — all platform-independent.
For images, use a separate CDN (Cloudflare Images, imgix) instead of next/image's default loader.
The migration checklist
When it's time to move: Audit your imports — search for '@vercel/' in your codebase. Each hit is a migration task. Replace @vercel/analytics with a platform-neutral alternative.
Replace next/image with unoptimized: true in next.config or use a third-party loader. Replace Vercel KV/Blob with direct Redis/S3 connections. Replace Edge Middleware with Cloudflare Workers or a reverse proxy rule.
Test with output: 'export' — if it builds, you're already portable. The more of these you do proactively, the easier migration becomes when costs force the decision.
Case study: Wes Bos moved from Next.js
In early 2024, after his viral video about jmail's $46k bill, Wes Bos publicly discussed moving some of his own projects away from Next.js. His reasoning, as shared in public discussions at the time: Next.js had become too Vercel-coupled, and the cost structure wasn't transparent enough. (Vercel has since made changes to pricing and spend controls — the situation may look different today.) You don't have to go that far.
Next.js with output: 'export' is essentially a static site generator — zero Vercel dependency. But the lesson stands: if your framework's default architecture ties you to one provider, that's a cost risk.
The HostCost approach
This site has zero Vercel-specific dependencies. Check our package.json: no @vercel/* packages. All calculations run in pure TypeScript.
All content lives in .ts files. The entire site exports to static HTML and can be deployed to any CDN with a single file copy. That's not just a technical choice — it's a business choice.
When your hosting bill depends on a single provider, you need the ability to leave. Portability is the ultimate cost optimization.
Want to see these principles in action?