Skip to content
Dashboard
Create 5 min read

Postgres

Provision a private PostgreSQL database with durable storage and generated connection credentials.

Postgres#

Choose Postgres to provision a private PostgreSQL database for services in your workspace. The service creation flow sets aside durable storage for that database and surfaces generated connection credentials scoped to the workspace. The database is reachable only from workspace services — it is never given a public hostname — which aligns its production boundary with the applications that read from it.

This integration is intentionally minimal: Postgres is there to persist what your service treats as durable rows — orders, users, sessions with durability — rather than to replace application-file storage or blob storage.

When to use — and when not to#

Use Postgres when:

  • The deliverable needs durable relational rows: users, orders, credits, entitlement records, job metadata.
  • Multiple services in the workspace should read and write the same domain data.
  • You benefit from transactional guarantees and typed, relational shape rather than bespoke file persistence.

Do not use Postgres when:

  • The state is ephemeral and safe to lose on restart (in-memory cache, transient job numbering) — consider whether durability is actually required.
  • A static-only service (a site with no process) requests "a database attached to the deployment" — static artifacts are files, not running servers with a persistent connection lifecycle; keep data where a service that runs a process can own it.
  • Blob and object storage is the primary need — create the application-owned persistence decision alongside the database and wire each explicitly rather than coalescing everything through rows.

Connect an application#

Create the database first, then copy its displayed connection details into the environment configuration of the service that needs to talk to it.

A reliable ordering:

  1. In New Project, choose Postgres. The creation flow allocates storage and shows the generated connection credentials — often as a single connection string (URL form) or as a host / port / database / username / password set. Treat that screen as authoritative for that release of the database; it can change between revisions and should not be memorized.
  2. Open the service that will read from the database (for example a Web Service or Background Worker).
  3. Add the connection string as an environment variable on that service. Treat the connection string as a secret: scope it to Runtime (or Both only when the application’s build legitimately needs to read it), do not prefix it with a browser-exposed prefix such as NEXT_PUBLIC_ or VITE_, and do not commit it.
  4. In application code, read the variable from the environment at startup and establish the connection. The exact client library shape differs by language, but the pattern is the same:
ts
// Node example (any PostgreSQL client)
const connectionString = process.env.DATABASE_URL;
if (!connectionString) throw new Error("DATABASE_URL is required");
const pool = new Pool({ connectionString });

Do not put the connection string in browser code or commit it to a repository — that exposure preserves the secret in history even after you rotate it. Similarly, avoid placing it in logs, issue text, or shared deployment screenshots. The deployment detail records that a connection *is configured*; the value itself stays workspace-private.

Tip

Pulte that the build that ran with a previous value no longer represents the same DATABASE_URL? Deploy again after rotating the secret so the next release’s observed environment and logs are consistent with the rotated value. Stale environments reading cached credentials produce confusing cross-mismatch logs.

Operations#

Manage the database through its project and service screens — the same place you created it. Day-to-day operations fall into three categories:

  • Connection and secrets hygiene. Rotate the credential the moment it was ever captured into a log, screenshot, or repository. The application must then pick up the rotated value on its next deployment; keep the old and new environment values coordinated so the roll does not leave the app pointing at the previous secret.
  • Schema and migrations. Run migrations from the service that owns the connection — usually as a deployment-gated build/start step or an explicit migration invocation against the value stored in the environment. A migration that fails mid-transaction should be retried following the application’s idempotent migration policy, not by re-provisioning the database.
  • Data lifecycle and backup. Before making destructive schema or data changesDROP, mass DELETE or UPDATE without tight predicates, major index rebuilds on large tables — create and verify a backup plan appropriate for the application. The platform provenance around each deployment (time, build, launching config snapshot) is independent of the backup strategy you choose for rows — they are separate layers.
Warning

Do not use the deployment artifact as the data store. Putting uploads or mutable state into the image filesystem or the static publishing directory is not durable — the next successful release can replace it.

Troubleshooting#

SymptomLikely causeFix
password authentication failedThe application still reads a previously rotated connection string, or the environment variable was scoped so it never reached the runtimeConfirm the database’s current displayed credentials, the variable’s scope, and redeploy the application service so the new environment is active.
Connection timeoutThe caller is not a workspace service, or the connection detail was taken from a previous revisionRead the current connection details from the database screen and check which workspace the caller lives in.
Build succeeds but migration/start failsThe migration retries are not idempotent or the snapshot was applied with the wrong environment valueRe-run the migration from a service configured with the current DATABASE_URL; preserve its output before retrying.
  • Environment Variables — scope the connection string so runtime, not build plumbing, carries the secret.
  • Storage and Release Artifacts — how immutable artifacts and durable rows separate.
  • Logs — reading per-deployment output when a migration or connect step fails.
  • Deployments — observing which DATABASE_URL-configured release actually ran.