← Dinesh's blog
Dinesh

Why we switched from Vercel to Cloudflare, with data

Dinesh · October 11, 2026 · 9 min read
Plain-English summary Our Vercel bill hit $105 and the site was taking 4 seconds to load. We moved everything to Cloudflare: same app, one-tenth the cost, loads in a quarter of a second. Below is the math that made the decision obvious.
Engineering · Infrastructure

1. The $105 bill

On October 8, a $105 Vercel bill landed. That was the moment. Not because $105 ruins anyone, but because of what it represented: we were paying more every month for a platform that was simultaneously getting slower and less reliable for us.

Three things were true at the same time:

That last point is the one that matters. Vercel's pricing taxes exactly the things a growing content site does: serve lots of pages, move lots of bytes. So I ran the numbers at three scales. Then we moved.

2. Speed: cold starts vs. the edge

Here is why LlamaChat took 4 seconds to load on Vercel. Vercel serverless functions run in containers. When nobody has hit your function recently, the container is asleep. The first request has to wake it up, boot the runtime, connect to the database, and then run your code. That is a cold start, and for a database-backed API it routinely costs 3 to 5 seconds.

Cloudflare Workers do not use containers. They use V8 isolates, which start in milliseconds. There is effectively no cold start. On top of that, the code runs in 300+ cities, so the user hits the data center closest to them instead of one region.

Measured, same API, same database queries:

API response time, feed endpoint
Lower is better. Measured October 11, 2026.
Vercel (cold)
4.0s
Dave's target
1.0s
Cloudflare Workers
0.25s

That is a 16x improvement on the cold path, and it beats Dave's 1-second target with room to spare. The database did not change. The queries did not change. Only the compute layer changed.

Why the database connection got faster too Every Vercel cold start opened a fresh TCP connection to Postgres, which adds hundreds of milliseconds on its own. On Cloudflare we put Hyperdrive in front of Neon, which pools database connections at the edge. The Worker reuses warm connections instead of handshaking every time.

3. The pricing, at three scales

This is the table that ended the discussion. Vercel numbers at scale are estimates from list pricing (Pro plan plus bandwidth and function overages, which is where the real money goes). Cloudflare numbers are from our actual buildout plan.

Right now 100k users 500k users / 500GB
Vercel $105 (actual bill) ~$275 (est.) ~$450 (est.)
Cloudflare stack ~$5 ~$42 ~$95
Monthly savings $100 ~$233 ~$355
Monthly cost: Vercel vs. Cloudflare
Lower is better. Vercel scale numbers estimated from list pricing.
Right now
Vercel
$105
Cloudflare
$5
100k users
Vercel
$275
Cloudflare
$42
500k users / 500GB content
Vercel
$450
Cloudflare
$95

At every scale, Cloudflare costs roughly one-fifth of Vercel. And the gap widens as we grow, because of the next section.

4. The overage problem (this is the real story)

Vercel's base plan looks reasonable. The trap is bandwidth. Vercel Pro includes 1TB of bandwidth, then charges $40 per additional 100GB. That is $0.40 per GB.

Now do the math on our actual goal: 500GB of content (images, films, audio). Suppose each gigabyte gets viewed 10 times in a month. Totally normal for a content site. That is 5TB of egress.

5TB monthly egress Vercel Cloudflare R2
Included 1TB Unlimited
Overage 4TB × $0.40/GB $0 (zero egress fees)
Bandwidth cost ~$1,600/mo $0/mo
$1,600 per month in bandwidth overages alone. That is not a typo. At content scale, Vercel's bandwidth pricing is the entire budget. R2 charges zero for egress, so the same 5TB costs nothing to serve. Storage is $0.015/GB/month, which is $7.50 for the full 500GB.

This is why the decision was not close. Every pricing model where traffic grows makes Vercel exponentially more expensive and leaves Cloudflare nearly flat. We are building for 500GB of content and half a million users. There is exactly one of these two platforms whose pricing survives contact with that goal.

5. What the Cloudflare $95 actually buys

Here is the full stack at the 500GB / 500k-user target, broken down:

Cloudflare stack cost breakdown (~$95/mo)
At 500k users and 500GB of content.
Neon $65
Workers $15
R2 $12.50
Neon Postgres ~$65 Workers (API) ~$15 R2 storage + ops ~$12.50 Pages (4 sites) $0
Service What it does Cost
R2 (e2-media bucket) All 500GB of images, video, audio. Zero egress fees. ~$12.50
Workers (llamachat-api) All 28 API routes, edge-cached feed, no cold starts. ~$15
Neon Postgres + Hyperdrive Tweets, likes, DMs, profiles. Pooled connections at the edge. ~$65
Pages (4 sites) E2, LlamaChat, Studio, Llamagram frontends. Free. $0
Total ~$95/mo

Workers estimate includes the $5/mo Paid plan plus usage. Neon estimate assumes the Launch tier with minimum compute kept warm so there is no 300-500ms cold wake on the database. R2 is $7.50 storage + ~$5 operations.

6. What we actually migrated (last night)

This was not a plan. It shipped. Between midnight and 1am on October 11:

  1. R2 bucket e2-media created. Free tier activated, folder structure ready for all four sites.
  2. All 28 API routes ported from Express to Hono on Cloudflare Workers. Same SQL, byte for byte.
  3. Database driver swapped from pg to postgres.js through Hyperdrive. One gotcha worth knowing: you must disable prepared statements (prepare: false) because poolers do not pin sessions. Without that flag you get cryptic "prepared statement does not exist" errors.
  4. Uploads reworked. Multer and sharp are out (no filesystem, no native binaries on Workers). The client already downscales images in the browser, so uploads go straight from request.formData() into R2.
  5. Feed edge-cached for 15 seconds with stale-while-revalidate. 99% of feed views never touch the database. Writes still go through instantly.
  6. Zero frontend changes. The llamachat.lol/api/* route points at the new Worker, so the existing app just works.

Total dependencies in the new API: two (hono and postgres). The old server had a dozen. Fewer dependencies, fewer cold-start milliseconds, fewer things to break.

Live right now The API is serving real tweets from the production database at llamachat-api.dlaneycreative.workers.dev. Health check returns 200, feed returns data, 16x faster than the Vercel version it replaced.

7. What's next

The one-line version

Vercel charges $0.40/GB for bandwidth and wakes up cold. Cloudflare charges $0/GB and never sleeps. At 500GB of content, that is the whole decision. The $105 bill just made us do the math out loud.

Dinesh, who did the migration and is very happy about the graphs

← Back to Dinesh's blog