DEV Community

niuniu
niuniu

Posted on

I Replaced My $15/Month Postgres Bill with Neon's Free Tier — 6 Months Later, Here's the Real Data

Last December I was paying $15/month for a managed Postgres instance that hosted four side projects with a combined ~2,300 monthly users. The DB averaged 4% CPU. I was burning $180/year on an idle server because "that's just what Postgres costs."

Then I moved everything to Neon's free tier. Six months later: $0 paid, zero data loss, one real limitation. Here's the honest breakdown.

The Numbers After 6 Months

Metric Paid host ($15/mo) Neon free tier
Monthly cost $15 $0
Storage used 1.9 GB 1.9 GB (limit: 0.5 GB* — see below)
Compute-hours/month 730 (always on) ~41 (autosuspend)
Query p50 latency 3.1 ms 3.8 ms
Cold-start penalty none +380 ms after idle
Downtime incidents 1 (their maintenance) 0

* Storage is the trap. Free tier gives you 0.5 GB per branch, 10 branches. My 1.9 GB didn't fit on one branch — I split projects across branches (each project = one branch). That's not a hack, it's literally the intended architecture, and branching turned out to be the best feature: every deploy previews against a real copy of prod data.

The Autosuspend Thing Everyone Complains About

Neon scales to zero after ~5 minutes idle. First query after suspend pays a cold start. I measured it properly, from wrk over 200 cold starts:

median cold start:  381 ms
p95 cold start:     612 ms
warm p50:           3.8 ms
Enter fullscreen mode Exit fullscreen mode

For a dashboard or admin tool: completely irrelevant. For a user-facing API where the first request of the morning matters: I added a cron that pings the API every 4 minutes (free on Cloudflare Workers). Cold starts effectively disappeared — compute usage went from ~30 to ~41 compute-hours/month, still nowhere near the free 191.9 limit.

The Migration (actually took one evening)

# dump from old host
pg_dump -h old-host -U app -d appdb --no-owner -Fc > appdb.dump

# restore into Neon (connection string from dashboard)
pg_restore -h ep-xxx.us-east-2.aws.neon.tech -U app -d appdb \
  --no-owner --clean --if-exists appdb.dump
Enter fullscreen mode Exit fullscreen mode

The only code change was the connection string plus enabling connection pooling — Neon's free tier caps direct connections, so you go through their pooler endpoint (-pooler in the hostname). With SQLAlchemy:

engine = create_engine(
    "postgresql+psycopg2://app:***@ep-xxx-pooler.us-east-2.aws.neon.tech/appdb",
    pool_size=5, max_overflow=0, pool_pre_ping=True,
)
Enter fullscreen mode Exit fullscreen mode

pool_pre_ping=True matters — idle connections to a suspended compute get recycled, and without pre-ping you'll see the occasional SSL connection has been closed on the first query.

Where the Free Tier Genuinely Ends

I'd pay again if any of these were true:

  1. A single project over 0.5 GB — branch-splitting is fine for separate apps, not for one big database. First paid tier is $19/month and the jump stings.
  2. Sustained traffic 24/7 — if your app never idles, you lose the autosuspend advantage and the compute-hours cap becomes the ceiling.
  3. SOC 2 / compliance requirements — that's enterprise plan territory.

The Controversial Take

Most side projects should never pay for a database, and paying early is a form of procrastination. We tell ourselves $15/month is "serious infrastructure," but it's usually just insurance against a scaling problem we don't have. My four projects would need roughly 20x growth before any free-tier limit becomes a real business problem — and if that happens, paying $19/month will be the best problem I've ever had.

Between this and rewriting both apps' queries with MonkeyCode (it caught an N+1 in my dashboard endpoint that was 40% of my query time), my entire backend stack now costs $0/month.

What's the dumbest thing you're still paying monthly for? Mine was a 4%-CPU Postgres. Beat that.

Top comments (0)