Connect Your App to Managed PostgreSQL with DATABASE_URL (Node.js, Python, Go)
Connect Node.js, Python (Django, FastAPI, SQLAlchemy) and Go apps to managed PostgreSQL with DATABASE_URL: private networking, migrations and backups.
- Published
- Reading time
- 4 min
On this page
Key takeaways
- Attach a managed PostgreSQL database and its connection string is injected as DATABASE_URL over a private network.
- Node.js (pg, Prisma), Python (Django, SQLAlchemy) and Go (pgx) all read the same variable.
- The Free plan includes 1 database with 500 MB that never pauses or expires; backups start on Hobby.
Hard-coded database credentials are the classic way an app breaks between your laptop and production. The fix is old and simple: read one connection string, DATABASE_URL, from the environment, and let the platform fill it in.
This guide shows how that works with a managed PostgreSQL database on DockHosting, with copy-paste code for Node.js, Python and Go.
How it works
- Create a PostgreSQL database from the dashboard. It's ready in seconds.
- Attach it to your project.
- Its connection string is injected into every connected app as
DATABASE_URL.
The database is reached over a private network through an internal hostname. Nothing is exposed to the internet by default, and your app and database sit in the same region (eu-central-1), so queries don't pay cross-region latency.
A DATABASE_URL looks like this:
postgresql://USER:PASSWORD@HOST:5432/DATABASENever commit it. Locally, put it in a .env file that's in .gitignore. In production, the platform sets it.
Node.js
With node-postgres:
import pg from "pg";
export const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
const { rows } = await pool.query("select id, email from users where id = $1", [userId]);With Prisma, point the datasource at the variable:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}Drizzle, Knex, TypeORM and Sequelize take the same string. Always use parameterized queries ($1) rather than string concatenation to stay safe from SQL injection.
Python
Django
Install dj-database-url and read the variable in settings.py:
import dj_database_url
DATABASES = {"default": dj_database_url.config(conn_max_age=600)}When manage.py is detected, migrate runs automatically before traffic switches to the new release, so your schema is always ahead of your code.
FastAPI / SQLAlchemy
import os
from sqlalchemy import create_engine
url = os.environ["DATABASE_URL"].replace("postgresql://", "postgresql+psycopg://", 1)
engine = create_engine(url, pool_pre_ping=True)The replace call selects the psycopg 3 driver. pool_pre_ping quietly replaces stale connections, which matters on the Free plan, where apps sleep when idle.
Go
With pgx:
pool, err := pgxpool.New(ctx, os.Getenv("DATABASE_URL"))
if err != nil {
log.Fatal(err)
}
defer pool.Close()
var now time.Time
err = pool.QueryRow(ctx, "select now()").Scan(&now)Go apps compile to a single static binary on deploy and wake in under a second.
Running migrations
- Django:
migrateruns automatically on deploy. - Rails:
db:migrateruns automatically on deploy. - Laravel:
artisan migrateruns automatically on deploy. - Node.js / Go: run your migration tool as part of your build or start command, for example
"start": "prisma migrate deploy && node dist/server.js". You can override the build and start commands per project in the dashboard.
Querying from your terminal
To check data quickly, dock db sql runs a SQL query against one of your managed databases from the CLI. You don't need to open a port or install a client. On Pro and Team you also get a database admin panel in the browser.
Limits by plan
| Free | Hobby | Pro | Team | |
|---|---|---|---|---|
| Managed databases | 1 | 2 | 6 | 15 |
| Storage per database | 500 MB | 2 GB | 5 GB | 20 GB |
| Daily backups | - | Kept 3 days | Kept 7 days | Kept 30 days |
| Public access (psql, pgAdmin) | - | Yes | Yes | Yes |
| Admin panel | - | - | Yes | Yes |
Free databases don't pause and don't expire. Read more on managed PostgreSQL hosting or compare plans.
Using other databases
The same pattern works for every engine. MySQL and MariaDB use DATABASE_URL, MongoDB uses MONGODB_URI, Redis uses REDIS_URL and ClickHouse uses CLICKHOUSE_URL. Attach the database, then read the variable.
New to deploying? Start with deploying a Node.js app in one command.
Related: Moving a Render free Postgres before it's deleted · Free backend hosting with a database that doesn't expire
Frequently asked questions
Which PostgreSQL version do managed databases run?
PostgreSQL 16 by default, with 15 and 14 available. Minor upgrades are applied for you.
Is there a free PostgreSQL database?
Yes. The Free plan includes 1 managed database with 500 MB of storage. It doesn't pause when idle and doesn't expire.
Can I connect with psql or pgAdmin from my laptop?
Public access for tools like psql and pgAdmin is available on Hobby and up. On every plan, your apps reach the database over the private network, and you can run queries from the terminal with dock db sql.
Are databases backed up?
Paid plans get daily automatic backups, kept 3 days on Hobby, 7 days on Pro and 30 days on Team.
- PostgreSQL
- Databases
- Node.js
- Python
- Go
- Tutorial
Written by Doughmi ILYAS
Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.
