Guides
External database
Astrodock can hand each app its own database automatically, or you can point an app at a Postgres you run somewhere else — Neon, Supabase, Amazon RDS, anything that speaks Postgres. This guide covers the external option and, importantly, why your app code stays exactly the same.
Internal or external?
Every app picks a database mode in its app.json. There are three:
| Mode | What Astrodock does | Reach for it when… |
|---|---|---|
internal | Auto-provisions a Postgres database on the bundled server and injects the connection details. | You just want a database and don't care where it lives. The easy path. |
external | Nothing is provisioned. You supply the connection string as a secret; the deploy is blocked until you do. | You have a managed Postgres already, need it outside the box, or want point-in-time backups, read replicas, etc. |
none | No database, nothing injected. | The app doesn't need one. |
Not sure? Start internal
The built-in Postgres is real Postgres, backed up with the rest of the stack. You can move to external later — it's a config change, not a rewrite. Switching is covered at the bottom of this page.
Step 1 — Set the mode in app.json
In your app's app.json, set the database mode to external:
{
"schemaVersion": "1",
"slug": "crm",
"name": "CRM",
"subdomain": "crm",
"runtime": { "type": "node" },
"auth": { "mode": "platform" },
"database": { "mode": "external" },
"storage": { "mode": "none" }
}
Then apply it so Astrodock knows the app expects an external database:
astrodock apply
Step 2 — The deploy is blocked until you set the URL
When a database is external, ASTRODOCK_DATABASE_URL becomes a required secret.
Astrodock won't deploy the app until that value exists — this is the required-variable gate. If you
try to deploy first, the CLI tells you exactly what's missing:
Deploy blocked — set these first (astrodock set-secret KEY):
- ASTRODOCK_DATABASE_URL (required for external-mode resource)
Set the connection string. You can pass it as an argument:
astrodock set-secret ASTRODOCK_DATABASE_URL 'postgresql://user:pass@host:5432/dbname'
…or pipe it in from stdin so it never lands in your shell history:
printf '%s' 'postgresql://user:pass@host:5432/dbname' | astrodock set-secret ASTRODOCK_DATABASE_URL
Prefer the dashboard?
Open the app, go to the Env tab, and set ASTRODOCK_DATABASE_URL there
instead. Same result. See Secrets & environment variables for the full tour.
Connection-string examples
The value is an ordinary Postgres connection string. A few common providers:
Neon
postgresql://user:password@ep-cool-name-123456.us-east-2.aws.neon.tech/dbname?sslmode=require
Supabase
postgresql://postgres:password@db.abcdefghijklmnop.supabase.co:5432/postgres
Amazon RDS
postgresql://user:password@mydb.abcdef123456.us-east-1.rds.amazonaws.com:5432/dbname
SSL
Most managed providers require TLS. If connections fail, add the provider's recommended SSL
parameter (often ?sslmode=require) to the URL, exactly as their dashboard shows it.
Your app code does not change
This is the part that surprises people. Whether the database is internal or external, your app reads the same variable:
import postgres from 'postgres';
const sql = postgres(process.env.ASTRODOCK_DATABASE_URL);
Astrodock injects ASTRODOCK_DATABASE_URL either way — for internal it's the URL of the
database it provisioned for you; for external it's the value you set. The name is identical, so the
app never knows the difference. (You also get ASTRODOCK_DATABASE_ENGINE=postgres in both modes.)
Switching internal → external
Graduating an app from the built-in database to a managed one is a value change, not a code change:
-
Migrate your data first
Astrodock does not copy data for you. Export from the internal database and import into the new one (for example with
pg_dump/pg_restore) before you switch, or you'll point a working app at an empty database. -
Flip the mode
Set
"database": { "mode": "external" }inapp.jsonand runastrodock apply. -
Set the new URL
astrodock set-secret ASTRODOCK_DATABASE_URL '…your new connection string…' -
Deploy
Run
astrodock deploy:watch. The app now reads the newASTRODOCK_DATABASE_URLwith no code edits.
Data is not copied for you
Switching modes only changes which database the app connects to. The old internal database and its contents are left as-is. Move the data yourself first.
Next steps
- Add file storage too: External object storage
- How secrets and the deploy gate work: Secrets & environment variables
- All the fields in
app.json: App structure & app.json