There are two ways to provision Render Postgres: the Render Dashboard and a Blueprint. Both end at the same place - a running instance with a connection string. The difference is repeatability.
This step covers both flows and the fields you absolutely have to get right the first time.
The Render Dashboard: best for one-offs and exploration
flowchart LR dash["Dashboard:<br/>+ New → Postgres"] fields["Pick name, region,<br/>plan, version, storage"] click["Click Create Database"] ready["Provisioned in<br/>~1 min, URLs live"] dash --> fields --> click --> ready
Use the Render Dashboard when:
- You’re prototyping and you might delete the database in an hour.
- You want to poke at settings interactively before committing them to YAML.
- The database is a one-off (e.g. a temporary analytics DB for a one-time report).
The Render Dashboard creates exactly one instance. There’s no rollback if you mistype the name - you’d delete and re-create.
Blueprint: best for anything you’ll run for more than a week
databases: - name: app-db plan: basic-256mb region: oregon postgresMajorVersion: "16" databaseName: appdata user: appuser diskSizeGB: 5A Blueprint declares the database alongside the services that consume it. The whole topology lives in one file, the file lives in Git, and render blueprints validate checks it before you sync.
Use a Blueprint when:
- You’ll have more than one environment (production + staging).
- You want a teammate to spin up an identical copy with one PR.
- You want infrastructure-as-code-style review on database changes.
For the validation loop and IDE setup, see the advanced Blueprint patterns intro. Everything in this step works with both a Blueprint-managed database and a Render Dashboard-managed one.
The fields you cannot change later
This is the part most worth slowing down on. Five fields are immutable after the instance is created. You cannot edit them in the Render Dashboard or the Blueprint after the database exists.
| Field | Why it’s locked |
|---|---|
name (Blueprint resource id) | The identifier fromDatabase references - renaming would orphan every consumer |
databaseName | The actual database name in the connection URL path |
user | The Postgres role used by the connection string |
region | Postgres data lives on regional storage; moving = a new instance |
postgresMajorVersion | Major upgrades are not in-place edits |
flowchart LR create["Create database"] immutable["name<br/>databaseName<br/>user<br/>region<br/>postgresMajorVersion"] changeable["plan<br/>diskSizeGB (only up)<br/>HA on/off (per plan)<br/>read replicas<br/>display name"] create --> immutable create --> changeable immutable -.->|"never"| edit1["Edit"] changeable -->|"yes, in the Render Dashboard or a Blueprint"| edit2["Edit"]
The Render Dashboard display name - what you see in the sidebar - can be renamed. That’s distinct from the Blueprint resource name (the id used by fromDatabase) and from databaseName (the actual database). All three sound similar; only one is mutable.
A safe creation checklist
Before you click Create or git push:
- Region matches your services Same region as the services that will hit
DATABASE_URL. Cross-region adds tens of ms per query. - `postgresMajorVersion` is the latest supported Or whatever your team standardizes on. Major upgrades later require a new instance and a migration.
- `databaseName` is what your migrations expect Most ORMs default to
postgresor your app name. Match what your migration tooling will look for. - `user` is something you can remember It shows up in
pg_stat_activityqueries forever.appuseror your app slug is fine. - `plan` is the right starting point You can resize plan later (with brief downtime). Start small if unsure - moving up is easier than the other way.
- `diskSizeGB` covers next 6 months 1 GB or multiples of 5 GB. You can grow it; you can never shrink it. Start conservatively.
Storage: 1 GB or multiples of 5 GB
The valid initial sizes are 1 GB (the minimum) or multiples of 5 GB: 5, 10, 15, 20, and so on, up to the plan’s maximum. Pick a size that covers your expected next 3 to 6 months of growth - autoscaling kicks in when you fill up (covered in step 05) but it has cooldowns and is one-way.
databases: - name: small-app-db plan: basic-256mb diskSizeGB: 1 # the minimum
- name: typical-app-db plan: basic-1gb diskSizeGB: 10 # ~3-6 months for a typical SaaS
- name: heavier-app-db plan: pro-4gb diskSizeGB: 50If you’re not sure, pick 1 GB and let autoscaling take care of growth. You’ll only pay for what you have, and the extra steps from autoscaling are background events you’ll never notice in normal operation.
What if I picked the wrong immutable field?
There’s no in-place edit, but there’s a clean recovery path: restore a snapshot to a new instance with the right settings.
- Provision a new database with the corrected settings New
region, newpostgresMajorVersion, newuser, whatever you got wrong. Differentnameso the old one isn’t disturbed. - Take a snapshot of the old database Either the most recent automatic snapshot, or
pg_dumpfor portability. - Restore the snapshot to the new instance Either via the Render Dashboard’s Restore flow or
pg_restorefor-Fcdumps. - Cut over consumers Update
fromDatabasereferences in your Blueprint to point at the new database name. Sync. Services pick up the newDATABASE_URLon next deploy. - Delete the old database Once you’ve verified the new one works for at least a deploy or two, remove the old database from the Blueprint and delete it.
The whole thing is a couple of hours plus however long the restore takes - annoying, not catastrophic. The cleanup steps for backups and pg_dump are covered in step 08.
What you learned
- Two creation paths: the Render Dashboard for one-offs, Blueprint (`databases:` block) for anything you'll keep
- Five immutable fields after creation: `name`, `databaseName`, `user`, `region`, and `postgresMajorVersion`
- Storage: `1 GB` minimum or multiples of `5 GB`. You can grow it later, but never shrink it
- Plan, disk size (up only), HA, read replicas, and display name are all mutable - adjust them later as you learn how the workload behaves
- When you need to change an immutable field: create a new instance, restore a snapshot or `pg_dump` into it, repoint consumers, delete the old one