pgrun.dev Docs
Managed PostgreSQL that spins up in a couple of minutes. Connect, and we handle backups, monitoring, and upgrades.
Overview
Every pgrun.dev database is a dedicated, isolated PostgreSQL instance — not a shared schema. You get a standard Postgres connection string and can use it with any language, framework, or GUI tool. We take care of the rest:
- Automated backups — daily base backups plus continuous WAL, stored off-site.
- Metrics & logs — CPU, memory, connections, cache hit ratio, and live server logs in the dashboard.
- Encrypted connections — TLS is required on every connection.
- One-click resize & upgrades — grow compute or storage, or move to a new Postgres version.
Create a database
In the dashboard, pick a server size, storage, and PostgreSQL version, then continue to payment. Your database provisions and is usually ready in 3–6 minutes — you'll get a "database is ready" email when it's live.
Connection string
Open your database in the dashboard → Overview, and copy the connection string. It looks like this:
postgres://USER:PASSWORD@HOST:5432/postgres?sslmode=require&channel_binding=require
Most drivers and tools accept this URL directly — as a DATABASE_URL environment variable, or split into host/port/user/password/database fields.
Connecting with psql
Paste the whole connection string:
psql "postgres://USER:PASSWORD@HOST:5432/postgres?sslmode=require"
Then run a quick check:
SELECT version();
\l -- list databases
\dt -- list tables
Connecting from your app
Set the connection string as DATABASE_URL and let your framework read it.
Ruby on Rails
# config/database.yml
production:
url: <%= ENV["DATABASE_URL"] %>
Node.js (node-postgres / Prisma)
// node-postgres
const { Pool } = require("pg");
const pool = new Pool({ connectionString: process.env.DATABASE_URL, ssl: { rejectUnauthorized: true } });
// Prisma — schema.prisma
datasource db { provider = "postgresql"; url = env("DATABASE_URL") }
Python (psycopg / Django)
# psycopg
import psycopg
conn = psycopg.connect(os.environ["DATABASE_URL"])
# Django settings.py
import dj_database_url
DATABASES = { "default": dj_database_url.parse(os.environ["DATABASE_URL"]) }
GUI tools
Any standard PostgreSQL client works. Paste the connection string, or fill the host / port / user / password / database fields from your Overview page — and make sure SSL is enabled.
- TablePlus — create a PostgreSQL connection, set SSL mode to "require".
- DBeaver — new PostgreSQL connection → SSL tab → enable "Use SSL".
- pgAdmin — register server → Connection tab, and set SSL mode to "require".
SSL & security
Every connection to a pgrun.dev database is encrypted with TLS — plaintext connections are rejected. Use sslmode=require (or stronger). For the strongest protection against man-in-the-middle attacks, keep channel_binding=require in the connection string, which most modern drivers support.
Metrics
The Metrics tab draws a chart for every performance signal — with value and time axes, gridlines, and hover readouts — over a selectable range from 1 hour to 30 days (all times UTC). Use them to spot saturation before it becomes an outage.
| Metric | What it measures | What to watch for |
|---|---|---|
| CPU Usage | CPU time across user, system, iowait, and steal modes. | Sustained high user/system time → consider a larger server. |
| Load Average | Average CPU demand over 1/5/15 minutes. | Above your core count = processes waiting for CPU (overload). |
| Memory Usage | Used, cached, and buffered memory. | Used consistently >90% can degrade performance. |
| Disk Usage | Data directory space (tables, indexes, WAL, logs). | Near 100% → increase storage before writes fail. |
| Disk I/O | Read/write operations per second. | Sustained highs indicate an I/O-bound workload. |
| Network Traffic | Inbound/outbound bytes per second. | Unusual spikes may signal a runaway query or client. |
| Connection Count | Active and total client connections (max 500 default). | Near the limit → add pooling (PgBouncer) or raise it. |
| Cache Hit Ratio | Share of reads served from cache. | Normally >99%; lower suggests more memory would help. |
| Operation Throughput | Rows fetched/inserted/updated/deleted per second. | Sudden changes = a shift in your workload. |
| Deadlocks | Deadlock detection rate. | Non-zero often points to a locking/design issue. |
| Database Size | Size of your largest databases. | Unexpected growth to investigate. |
| Transactions | Committed and rolled-back transactions per second. | Rising rollbacks can indicate application errors. |
Query insights
The Queries tab shows where your database's time actually goes — broken down by the parts of your application. It works two ways:
- Zero setup: activity is automatically grouped by
application_name, database, and user. If your app setsapplication_name(Rails, most drivers do), you see a per-app breakdown immediately. - Query tags: add a SQLCommenter comment to your queries and group by any dimension you like — team, feature, endpoint:
SELECT * FROM orders WHERE user_id = $1
/*app='web',team='checkout'*/;
; belongs to a separate, empty statement and is ignored — this is the #1 tagging mistake. Keys and values are URL-encoded; keys are lowercased.Rails enables this with one setting — config.active_record.query_log_tags_enabled = true — and most ORMs have a sqlcommenter middleware.
How to read the numbers
Insights are sampled: we observe active queries five times a second and attribute time slices to their tags. That yields % of runtime, % of CPU time, and active time — an honest picture of where time goes. It does not measure per-query latency or call counts; the percentile pills above the chart (p50/p95/p99/max) are percentiles of the activity rate (how bursty a tag's load is), not latency.
Limits to know
| Limit | Behavior |
|---|---|
| 20 distinct values per tag key | Extra values collapse into __collapsed__ and the page shows a high-cardinality warning. Don't tag with user IDs or request IDs. |
| Query text length | Postgres clips query text at track_activity_query_size (default 1024 bytes) and the tag comment is the part that gets cut. If you tag long queries, set it to 4096 in Settings → Configuration (takes effect after a restart) — the page warns you when clipping is detected. |
Top queries
Below the tag charts, the Top queries table lists your heaviest query patterns from pg_stat_statements — exact numbers, cumulative since statistics began. Click any query to expand the full SQL; click a column header to sort; switch between the top 15 and top 50.
| Column | Meaning |
|---|---|
| Count | Executions of this query pattern. |
| Total time / Avg / Max | Cumulative, mean, and worst execution time. |
| Rows / Rows per call | Rows returned or affected — a high rows-per-call often means a missing LIMIT or index. |
| Cache hit | Share of block reads served from shared buffers; low values mean disk-bound. |
| Time share | This query's total time relative to the heaviest query. |
Expanding a query also shows its write-side footprint: blocks dirtied, temp spill, and WAL produced.
CREATE EXTENSION pg_stat_statements; once and reload. Latency percentiles (p50/p99) per query aren't available from pg_stat_statements — they're coming with a future exact-metrics tier.Logs
The Logs tab streams your database's server logs with color-coded severity (INFO, WARNING, ERROR, FATAL). Choose a time range (30m / 1h / 2h / 4h) and how many lines to show (50 – 500). Logs are the fastest way to diagnose a failing query, a connection storm, or an authentication problem.
AI assistant
The Assistant tab is an AI DBA that answers questions about your database — "why was it slow in the last hour?", "what are my heaviest queries?", "any errors I should worry about?". It reads the same live data the dashboard shows (metrics, query stats, workload tags, logs, schema, backups) and cites the numbers it used. It is strictly read-only: it can look, EXPLAIN, and recommend, but never change anything.
Two more places AI shows up:
| Feature | What it does |
|---|---|
| Explain query | Expand any row in Top queries and click Explain query: a plain-English explanation of what the query does, how Postgres executes it (from a real EXPLAIN), and whether it's healthy for its call pattern. |
| Weekly report | Every Monday morning an AI-written summary of the last 7 days — health, heaviest queries, errors, and up to three concrete recommendations — is stored under Assistant and emailed to the account owner. |
hypopg (nothing is built) and re-plans the query. You only ever see suggestions the Postgres planner would actually use, with the measured cost change — never guesses.pg_stat_statements (literals become $1), so your data values are not part of the analysis.Agent API
Everything the AI assistant can see is also available to your agents and tools over a read-only JSON API: health context, top queries, metrics, logs, schema, and backups per database. Create a bearer token on the dashboard's Tokens page (account owner/admin), then:
curl -H "Authorization: Bearer pgrun_…" \
https://app.pgrun.dev/api/v1/databases/<name>?window=24h
The full endpoint list with response shapes lives in agents.md — written to be pasted straight into an LLM's context. Responses carry exactness labels (exact_window, scraped_15s, sampled) so agents summarize honestly. Tokens never expose connection strings; rate limit is 120 requests/minute.
Backups & restore
Backups run automatically — a daily base backup plus continuous write-ahead logs — and are stored off the database host, so a host failure never takes your backups with it. From the Backup / Restore tab you can restore to a new database at a point in time within the retention window.
Resize & upgrade
From your database's sidebar you can:
- Resize — increase compute (vCPU/RAM) or storage. Your monthly price updates to match.
- Upgrade — move to a newer PostgreSQL major version.
- High availability & read replicas — add standby/replica nodes for resilience and read scaling.
- Configuration — tune Postgres parameters.
Support
Stuck or have a question? Email support@postgresrun.com and we'll help. Include your database name so we can look it up quickly.