Build
Direct database connections
Point any Postgres tool at your app's database: db.atberth.com, port 5432, TLS, a login that only reaches your app. On Pro and up.
What it is
Every app is its own Postgres 17 database. On Pro, Agency and Business you can connect to it directly, with any tool that speaks Postgres: psql, TablePlus, DBeaver, Postico, Prisma, Drizzle, SQLAlchemy, Metabase, or Terraform's postgresql provider. Free apps use the SQL endpoint and the API instead.
The direct login has the same power as the app's secret key. Treat the connection string like that key: keep it on your machine or your server, never in a phone or browser app.
Turn it on and connect
berth db on --app "$APP"
# postgresql://app_demo_direct:…@db.atberth.com:5432/app_demo?sslmode=require
psql "postgresql://app_demo_direct:…@db.atberth.com:5432/app_demo?sslmode=require"
berth db psql --app "$APP" # or let the CLI open psql for you (this makes a new password)The password is shown once. Run berth db rotate to get a new one: the old one stops working and anyone connected with it is disconnected. berth db off removes the login. The same thing over HTTP, with the app's secret key:
curl -X POST https://api.atberth.com/v1/apps/$APP/database/connection -H "apikey: $SECRET" # on, or rotate
curl https://api.atberth.com/v1/apps/$APP/database/connection -H "apikey: $SECRET" # host, user, on or off
curl -X DELETE https://api.atberth.com/v1/apps/$APP/database/connection -H "apikey: $SECRET" # off| Setting | Value |
|---|---|
| Host and port | db.atberth.com:5432 |
| Database | app_<your app> |
| User | app_<your app>_direct |
| TLS | required. The certificate is a public Let's Encrypt one, so sslmode=verify-full works too. |
| Connections | 5 at a time per app. Use a pool in your server. |
| Statement time | 2 minutes. An open transaction that sits idle for 1 minute is closed. |
How it fits with the rest of Berth
- You connect as the app's owner, so tables you create in
psqlshow up in the API, the console and backups like any other. - Row policies apply to end users calling the API. A direct connection is a server-side login, like the secret key, and sees every row.
- Leave the
_berthschema alone. It holds your app's users, sessions and settings. - Writes made here skip the API's per-request row checks, so Berth checks the database size every hour. If the app is over its plan's size limit, or the server is short of disk, the login pauses (existing data stays and the API keeps working) and comes back on its own once that's fixed.
- If the account goes back to Free, the direct login is removed within the hour.
Security
Only logins named *_direct may connect from outside, only over TLS, only with SCRAM passwords, and only to their own app's database. Postgres's own accounts and Berth's internal ones cannot log in from the internet at all. Passwords are 32 random bytes. An address that fails to log in 10 times in 10 minutes is blocked for an hour, and longer if it keeps trying.
Terraform
Manage tables, extensions, roles and grants inside your app's database with the community cyrilgdn/postgresql provider pointed at the direct connection. The app itself, keys and settings stay in the API and CLI.
terraform {
required_providers {
postgresql = { source = "cyrilgdn/postgresql", version = "~> 1.25" }
}
}
variable "berth_db_password" { sensitive = true }
provider "postgresql" {
host = "db.atberth.com"
port = 5432
database = "app_demo"
username = "app_demo_direct"
password = var.berth_db_password
sslmode = "require"
superuser = false
}
resource "postgresql_extension" "trgm" {
name = "pg_trgm"
}
resource "postgresql_schema" "reporting" {
name = "reporting"
owner = "app_demo"
}For table definitions, most teams prefer a migration tool (Prisma Migrate, Drizzle Kit, Atlas, Flyway, sqitch) over Terraform. Any of them works with the same connection string.