Neon is the database provider Oolvay recommends officially. It is serverless Postgres with a genuinely usable free tier, instant project provisioning, and database branching built in. This page walks through getting a Neon project connected to Oolvay and what the free tier actually gives you.
Go to neon.com and sign up. No credit card is required for the free plan.
Click Create a project. Give it a name, for example your app’s name, and pick a region close to where your app will be deployed.
Neon provisions a root branch automatically. This is your primary database, equivalent to a main branch.
From the project dashboard, open Connection Details. Select Connection string and copy the full string. It looks like
postgresql://<user>:<password>@<host>/<dbname>?sslmode=requirePaste this directly into DATABASE_URL in your .env.local.
DATABASE_URL0 / 2,000 characters
Run the migrations.
bun db:migrateStart the development server and confirm the app starts without a connection error.
bun devOolvay connects with the standard postgres package against
this connection string, not Neon’s edge-specific HTTP driver. This means the
same connection string works identically in any runtime that supports a TCP
Postgres connection.
Neon’s dashboard offers more than one connection string format, a direct connection and a pooled connection. The difference matters even if you never think about it again after setup.
A direct connection talks straight to your database and gives it one dedicated slot per connection. Postgres can only hold a limited number of these open at once, typically a few hundred. A pooled connection instead goes through Neon’s built-in connection pooler (PgBouncer), which sits in front of the database and shares a much smaller number of real connections across many incoming requests.
This matters specifically because of how Next.js runs in production. Every serverless function invocation, every API route hit, can spin up a new, short-lived connection to your database. Under real traffic, that adds up fast enough to exhaust a direct connection’s limit and start throwing connection errors. A pooled connection absorbs that churn instead of choking on it.
For Oolvay, use the pooled connection string if one is offered. If your connection string contains -pooler in the hostname, that confirms it’s the pooled variant.
These figures are current as of this writing. Neon’s pricing has changed multiple times in the past year, so confirm current numbers on neon.com/docs/introduction/plans before architecting around any specific ceiling.
| Limit | Free plan |
|---|---|
| Projects | Up to 100 |
| Compute per project | 100 CU-hours per month, capped at 2 CU |
| Storage per project | 0.5 GB |
| Branches per project | Up to 10 |
| Egress | 5 GB per month |
| Point-in-time restore window | A few hours, not configurable |
| Scale to zero | Always on, cannot be disabled |
A Compute Unit, or CU, is roughly 1 vCPU and 4 GB of RAM at 1 CU, scaling down to 0.25 CU for lighter workloads. The 100 CU-hours and the 2 CU cap are two separate limits answering two separate questions.
The 100 CU-hours per month is a budget, the total amount of compute time you can spend across the month. A CU-hour is one Compute Unit running for one hour. Spend it on a smaller size and it lasts longer in wall-clock time, roughly 400 hours a month at the smallest 0.25 CU size, or roughly 100 hours a month at the full 1 CU size. Once the budget is used up for the month, compute suspends until the next billing cycle refills it.
The 2 CU cap is a ceiling, not a budget. Neon autoscales your compute size up and down with load, but on the free plan it will never scale past 2 CU, no matter how much of your monthly budget remains untouched. You can run out of monthly hours while staying small the whole time, or stay well within your monthly budget while still being capped during a traffic spike. They’re independent limits, and either one can be the thing that bites you first depending on your traffic pattern.
Scale to zero means your database suspends after a short idle period and wakes on the next request. On the free plan this is mandatory, not optional. The first request after a suspension carries a cold start delay, typically a few hundred milliseconds. For local development and most early production traffic, this is unnoticeable. For latency-sensitive production workloads with sparse traffic, it’s worth knowing about before launch.
Once a project exhausts its monthly CU-hour allowance, compute is suspended until the next billing cycle resets it. This is a hard cutoff on the free plan, not a soft throttle.
The 0.5 GB storage limit per project is comfortable for most early apps but worth monitoring once you’re storing logs, audit trails, or anything that grows without bound. Oolvay’s auditLog table, for example, has a retentionDays configuration in config/site.ts precisely so audit data doesn’t grow unbounded on a constrained plan.
Move off the free plan when any of the following apply.
Neon’s paid plans (Launch and Scale) bill purely on usage, with no flat monthly minimum charge beyond a small base fee, so moving off the free plan does not mean committing to a large fixed cost.
Because the free plan allows up to 100 projects, a common pattern is one Neon project for local development and a separate one for staging or production, each with its own DATABASE_URL. Alternatively, use Neon’s branching feature to create a branch off your production database for development, which starts with zero storage cost and only grows as it diverges from the parent.