Render Tutorials
Postgres on Render: a deep dive

What Render Postgres is

⏱ 6 min

Render Postgres is a fully-managed PostgreSQL database - Render runs the server, handles upgrades, takes daily backups, and exposes the database via a connection string. You write SQL; the operations are someone else’s problem.

This deep dive is for the moment after the “hello world” - when you have a basic database running and you want to know how to size it, scale it, secure it, back it up, and debug it without surprises.

Before you start

The tutorial is reference-shaped, so you can read it without touching anything. To follow along hands-on:

  • A Render account with at least one Postgres instance, or willingness to provision one in step 2. The free instance type works.
  • A Render service that already talks to a database, ideally. The first-deploy guide covers wiring an app to Render Postgres if you haven’t done it.
  • psql on your machine. The PostgreSQL client tools ship with most package managers (brew install libpq, apt install postgresql-client).
  • The Render CLI v2.7.0+ for render psql. Recommended but optional.
  • Comfort with SQL.

The Postgres docs and the Blueprint spec are good companions, especially for the wiring step.

The shape of it

flowchart LR
  app["Your service<br/>(web / worker / cron)"]
  internal["Internal URL<br/>(private network)"]
  external["External URL<br/>(public, TLS required)"]
  pg[("Postgres instance")]
  bk["Daily snapshots"]

  app -->|"DATABASE_URL"| internal
  internal --> pg
  external -->|"laptop, CI, BI tools"| pg
  pg -.-> bk

A few things to pin down before we go deeper:

  • One Render database resource = one Postgres instance. It can hold multiple logical databases (we cover that in step 04) but they share the host, the port, and the user.
  • Two URLs per instance - internal (for Render-hosted services) and external (for everything else). They point at the same data; they differ in network path and TLS rules. Whole step on this in 03.
  • You don’t get a managed connection pooler. Pooling is on you. We cover the math and the options in step 06.
  • Daily snapshots are automatic. Retention depends on your plan. PITR exists on paid plans. We cover the whole backup story in step 08.

What you get out of the box

FeatureNotes
Managed PostgreSQLCurrent major versions; Render handles minor upgrades
Daily snapshotsAutomatic, retention by plan
TLS for external connectionsAuto-provisioned
Internal private network accessSame-region Render services connect without TLS
Storage autoscalingGrows ~50% when you hit ~90% disk usage (with limits)
Read replicasUp to 5 per database
High availability (HA)On Pro plans + Pro workspace + PG 13+
Common extensionspg_stat_statements, pgvector, PostGIS, etc. - enable per database as needed

What you don’t get (and what to do instead)

Not includedWhat to use instead
Built-in connection poolerFramework pools (Rails, Django, Node pg) or PgBouncer you operate
Cross-region replicaspg_dump / pg_restore or self-managed logical replication
Per-query rate limitingAdd it at the app/proxy layer
Multi-masterPostgres doesn’t really; design around a single primary
Schema/object-level backupspg_dump selectively (-n schema, -t table)
In-place changes to immutable fieldsRestore a snapshot to a new instance with the desired settings

The “you don’t get a pooler” item is the one that bites the most teams. If you’ve come from a database service that ran one for you, plan for it from day one.

When Render Postgres is the right call

It’s the default for most Render apps. The shape of the workload that fits really well:

  • A single primary, optionally with a few read replicas.
  • Hundreds to low thousands of concurrent connections (with pooling).
  • Storage that grows incrementally and rarely needs to shrink.
  • A single region, with the app and the database in the same region.
  • Standard PostgreSQL extensions, no exotic kernel patches.

If you need any of these, you’re outside the comfort zone - talk to support or build a custom solution:

  • Massive analytical workloads that benefit from columnar engines.
  • Sub-millisecond latency worldwide (you’d want a different topology).
  • Pinned to a specific minor PG version that diverges from Render’s upgrade cadence.
  • Vendor-specific extensions Render doesn’t support.

The constraints that decide everything else

The rest of the tutorial loops back to four constraints. Worth knowing them up front so the later steps land:

  • Four fields are immutable after create: databaseName, user, region, and postgresMajorVersion. Plus the Blueprint resource name. Pick them carefully - changing any of them later means a new database and a migration.
  • Storage can grow but never shrink. Once you autoscale up, you’re up forever. Archive aggressively before the threshold.
  • Max connections are a hard limit, scaled by RAM. Going over throws errors at the app, not warnings - pool defensively.
  • readReplicas in a Blueprint is authoritative. An empty list destroys all your replicas. Treat it like a desired-state declaration, not a patch.

We dig into each of those in their own step. For now, the takeaway: Render handles the daily care, but the permanent decisions are yours.

The path through the tutorial

flowchart LR
  s1[01 introduction]
  s2[02 provisioning]
  s3[03 connection strings]
  s4[04 wiring]
  s5[05 storage]
  s6[06 pooling]
  s7[07 HA + replicas]
  s8[08 backups + PITR]
  s9[09 operations]

  s1 --> s2 --> s3 --> s4 --> s5 --> s6 --> s7 --> s8 --> s9

Each step stands on its own - skip ahead if you have a specific question. For a first read, the order above is the one I’d use.

Which of these does Render *not* include with Render Postgres out of the box?

What you learned

  • Render Postgres is a managed PG instance with internal + external URLs, daily snapshots, and integration with Blueprint wiring
  • You don't get a built-in pooler or cross-region replicas - plan for a framework pool or PgBouncer, and `pg_dump` for cross-region migrations
  • Four immutable fields decide permanent settings: `databaseName`, `user`, `region`, `postgresMajorVersion` (plus the Blueprint resource `name`)
  • Storage grows but doesn't shrink; max connections are a hard cap by RAM; `readReplicas` is authoritative declarative state