DEV Community

niuniu
niuniu

Posted on

I Replaced My $50/Month PaaS Bill with Cloudflare Workers + Neon — Here's the Exact Setup

Three months ago I was paying a well-known PaaS $50/month to host two small REST APIs. Total traffic: ~180K requests/month. That's 2.8 cents per 1,000 requests — for what is essentially a SELECT * FROM events WHERE user_id = $1.

So I moved everything to Cloudflare Workers + Neon. My bill is now $0.00/month. Not "$0 for the first year" — structurally $0, because both free tiers are way above my usage.

The Numbers

Metric Old PaaS Workers + Neon
Monthly cost $50 $0
Cold start 300–800ms 0ms (V8 isolates)
p50 latency (global) 95ms 31ms
Free-tier headroom 100K req/day + 0.5 GB storage
Deploy time ~2 min 8 seconds

I'm using roughly 6% of the Workers free tier (100K requests/day) and 40MB of Neon's 0.5GB free Postgres storage.

The Exact Setup

wrangler.toml:

name = "events-api"
main = "src/index.ts"
compatibility_date = "2026-08-01"

[placement]
mode = "smart"   # runs the Worker next to the Neon region — cut my p95 from 210ms to 60ms
Enter fullscreen mode Exit fullscreen mode

The Worker talks to Neon over HTTP using their serverless driver — no TCP pool to manage, no connection limits to hit:

import { neon } from '@neondatabase/serverless';

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const sql = neon(env.DATABASE_URL);
    const url = new URL(request.url);

    if (url.pathname === '/events' && request.method === 'GET') {
      const userId = url.searchParams.get('user_id');
      const rows = await sql`
        SELECT id, type, created_at FROM events
        WHERE user_id = ${userId}
        ORDER BY created_at DESC LIMIT 50`;
      return Response.json(rows);
    }
    return new Response('not found', { status: 404 });
  },
};
Enter fullscreen mode Exit fullscreen mode

Deploy:

npx wrangler deploy   # 8 seconds, live globally
npx wrangler secret put DATABASE_URL
Enter fullscreen mode Exit fullscreen mode

What I Actually Lost

Let's be honest, it's not all wins:

  • No long-running processes. 30s CPU limit on Workers. My nightly aggregation job moved to a cron-triggered Worker with chunked queries — annoying but works.
  • Postgres extensions are limited on Neon's free tier. No pg_cron. I use Workers Cron Triggers instead.
  • Cold storage suspension. Neon's free tier scales to zero after 5 min idle; first query after that takes ~600ms. For my traffic pattern it happens maybe twice a day. Acceptable.

The Controversial Take

For side projects and early-stage SaaS, paying for a VPS or PaaS in 2026 is a skill issue. Between Cloudflare (Workers, Pages, R2, D1), Neon, Supabase, Vercel, and Turso, you can run a real product with real users for $0 until you're making enough money that $50/month is a rounding error. The people paying $50–200/month for hobby projects aren't buying performance — they're buying the comfort of not learning a new platform.

I say that as someone who paid $600 over 12 months before spending one weekend learning Workers.

The AI pair-programmer I used to do the migration (including writing the wrangler config and porting my ORM code) was also free — I use MonkeyCode, an open-source coding assistant with a genuinely generous free tier. It ported 14 route handlers to the Workers fetch API with two small bugs I caught in review.

What's the dumbest thing you're still paying for that has a free-tier replacement? I have a suspicion a lot of us are paying for managed Redis when Cloudflare KV exists.

Top comments (0)