Databases
Understand the difference between scales-to-zero and always-on databases, what CU and CU-h mean, and how usage limits are enforced.
Overview
A project can run two kinds of database, and the choice is the first thing you make when you add one:
- Scales to zero — a Postgres database that sleeps when nothing is querying it. You pick a plan, and the plan includes a fixed amount of compute and storage.
- Always-on — a dedicated managed cluster that never sleeps. You pick an engine, a size and a region, and pay a fixed monthly price for that capacity.
Both are fully managed: backups, patching and failover are handled for you, and both hand you a connection string when they finish provisioning.
Choosing between them
| Scales to zero | Always-on | |
|---|---|---|
| Engines | PostgreSQL | PostgreSQL, MySQL, MongoDB |
| Idle cost | Compute stops while idle | Full price, always |
| First query after idle | Takes a moment to wake | Always warm |
| Sizing | Autoscales up to the plan's ceiling | Fixed vCPU and memory you choose |
| Price | Fixed monthly plan with included allowances | Fixed monthly price per node |
| High availability | Single compute | Optional standby nodes |
| What happens at the limit | Database is suspended, never overbilled | No usage limit to hit |
Rules of thumb:
- Development, staging, side projects, anything with quiet stretches — use scales to zero. An idle database costs almost nothing from its allowance.
- Steady production traffic, latency-sensitive endpoints, or an engine other than Postgres — use always-on.
- Cron-driven or bursty workloads — scales to zero still works well, but read the idle timeout section first: short, frequent visits keep the compute awake and consume more of the allowance than the query time alone suggests.
Scales to zero
The vocabulary
CU — compute unit, the size of the database's compute. One CU is one
vCPU with 4 GB of memory. 0.25 CU is a quarter of that.
CU-h — compute unit hour, one CU running for one hour. It is the unit your monthly compute allowance is measured in.
CU measures how fast the database can go at any one moment. CU-h measures how much compute it has used over the month. A plan sets both: a ceiling on the rate, and an allowance on the total.
Because the two are separate, the same allowance stretches differently depending on the size that is running:
| Compute size | Hours of uptime per CU-hour |
|---|---|
| 0.25 CU | 4 hours |
| 1 CU | 1 hour |
| 2 CU | 30 minutes |
A calendar month is about 730 hours. So a database that runs continuously at 1 CU consumes roughly 730 CU-h a month, and one that is awake for two hours a day at 0.25 CU consumes about 15 CU-h.
The database autoscales between a floor and the plan's ceiling, so it only draws the larger sizes while a query actually needs them. A mostly idle database on a 2 CU plan does not spend 2 CU-h per hour — it spends what the work costs.
Sleeping and waking
When nothing has queried the database for its idle timeout, the compute suspends and stops consuming the allowance entirely. The next query wakes it, which takes a moment — usually well under a second, occasionally a little more. Nothing is lost while it sleeps; your data is untouched and the connection string does not change.
The idle timeout is the number most likely to explain a usage figure you did not expect. Any open connection keeps the compute awake, and every visit holds it up for at least the full timeout after the last query. A database that is touched once every ten minutes by a health check is, in practice, awake all the time.
If usage looks higher than your query volume implies, look for:
- A connection pooler or ORM holding an idle connection open.
- A monitoring or uptime check hitting an endpoint that queries the database.
- A cron job running more often than the idle timeout is long.
Plans
| Plan | Price | Compute ceiling | Storage | Compute allowance | Sleeps after | Restore window |
|---|---|---|---|---|---|---|
| Hobby | $5/mo | 0.25 CU | 3 GB | 35 CU-h | 5 minutes | 1 day |
| Starter | $19/mo | 1 CU | 10 GB | 145 CU-h | 5 minutes | 1 day |
| Growth | $49/mo | 2 CU | 25 GB | 375 CU-h | 10 minutes | 3 days |
| Scale | $129/mo | 4 CU | 75 GB | 950 CU-h | 30 minutes | 7 days |
Every plan includes automatic point-in-time restore across the window shown above, and lets you pick the PostgreSQL major version when you create the database — anything from 14 to 18, defaulting to the newest. Pick an older one when an extension or framework you depend on is not ready for the latest. The version is fixed for the life of that database: moving to a newer major version means creating a new database and migrating your data into it.
Scale is the tier an always-on production workload lands on: its allowance clears 730 CU-h, so a 1 CU compute can stay up around the clock and never approach the cap.
The price is the whole price. There is no per-query, per-hour or per-gigabyte line on top — the plan's allowances are hard limits, not soft ones you get billed past.
Usage, warnings and suspension
The database's detail page carries a Usage this month card with a meter for compute and one for storage, each read live and shown against the plan's cap.
- Past 80% of a limit the meter turns amber. That is the point to consider moving up a plan, so that a suspension is never the first thing you hear about your usage.
- At 100% the compute is suspended and stops accepting queries. Your data is preserved and nothing is deleted; the database keeps showing in the panel with a Suspended status and an explanation of which limit it hit.
Compute and storage behave differently at the limit, and it matters:
- Compute is a per-period allowance that resets with each billing period. A compute-suspended database comes back on its own at the reset, or immediately if you upgrade.
- Storage does not reset — stored bytes stay stored. A database at its storage cap stays suspended until you either free up space or move to a plan with more room. This is deliberate: writes stop before storage can run away.
Retained history counts towards storage. A plan with a longer restore window is holding more data on your behalf.
Changing plan
The database's detail page lists every plan next to your current one. Selecting one asks you to confirm, and tells you what changes, before anything is charged. Changes take effect immediately and are prorated against your billing period.
- Moving up raises the limits straight away. If the database was suspended for exceeding its compute allowance, moving up starts it again immediately.
- Moving down applies the lower limits straight away too — if the database later reaches them, its compute is suspended until you move up again or the allowance resets.
- A smaller plan is unavailable while the database holds more data than that plan includes; it is marked Needs less storage and cannot be selected. Free up space first — the alternative is a cheaper plan that suspends the database the moment it applies.
Always-on
An always-on database is a dedicated cluster sized by you. There is no sleeping, no allowance and no usage cap: you are buying capacity, and the monthly price is the same whether you use it or not.
You choose:
- Engine and version — PostgreSQL, MySQL or MongoDB.
- Node type — Basic (shared CPU, for development and light production), General Purpose (dedicated CPU), Memory-Optimized (8 GB RAM per vCPU, for large working sets) or Storage-Optimized (large NVMe disks for data-heavy workloads).
- Size — vCPU, memory and included disk. Priced per node.
- Region — pick the one closest to the app that queries it.
- Standby nodes — up to two. A standby replicates the primary and takes over automatically if it fails. Each node is billed at the size's price, so a two-node cluster costs twice a one-node cluster.
- Extra storage — disk beyond the size's included amount, in 10 GB increments, billed per gigabyte per node.
For latency, put the database in the same region as the app that talks to it. Cross-region queries pay the round trip on every call.
Connecting
When provisioning finishes, you are shown the host, database name, user, password and a ready-made connection string. The password is shown once — copy it into your secret manager or your app's environment before leaving the page. See the Secrets guide for storing it.
If you lose it, rotate the password from the database's detail page and update whatever was using the old one. Rotating invalidates the previous password immediately.
Browsing your data
A scales-to-zero database has a Data tab on its detail page, next to Overview. It is there for looking at what the database actually holds without installing a client:
- Tables — every table and view the database's user can read, grouped by schema. Pick one to page through its rows, and click a column heading to sort by it. Row counts next to a table are estimates from the database's own statistics, not exact counts.
- SQL query — a box for running a single
SELECT,WITHorEXPLAIN.Ctrl/Cmd+Enterruns it.
Everything in this tab is read-only. Statements that would change data or
structure — INSERT, UPDATE, DELETE, DROP and the rest — are refused, and
the query runs inside a read-only transaction, so nothing typed here can alter
the database. To make changes, connect with your database credentials.
Two limits keep a query in the panel from disrupting the application using the
same database: a query is stopped if it runs longer than a few seconds, and only
the first rows of a large result are returned. Add a LIMIT and a WHERE clause
to work within both.
The tab is unavailable on databases created before it existed, because the panel holds no credential for them — only you have their password. Rotate the password from the Overview tab to enable it, and update anything already connected with the old one.
Waking a sleeping database to browse it uses compute from the plan's allowance, the same as any other query.
Doing this over the API
Both kinds of database can be created, resized and deleted over the API with a
key that has databases: read, write scope — see the
API Keys guide for issuing one. The endpoints are in the
OpenAPI document, which is generated
from the same schemas the API validates against.
Related: shared databases
Shared databases are a separate product from the two above. They exist for handing isolated, pooled databases on one shared PostgreSQL cluster to your own end-clients, rather than for running your own app's data. See the Shared Databases reference.