> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dbhost.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Core concepts

> Key concepts and terminology in DBHost.

## Databases

A database in DBHost is a PostgreSQL database with its own user, password, and PgBouncer pool slot. Each database is isolated from other databases, but access does not have to stay owner-only: owners can share a database with other existing DBHost users through database-level roles.

When you create a database from the dashboard, DBHost generates an internal PostgreSQL identifier from your display name and account. When you create one via the public API, you provide the database name directly using lowercase letters, numbers, and hyphens. In both cases, the final internal name becomes both the PostgreSQL database name and the username.

Dashboard lists can therefore contain:

* **Owned databases** — full owner control
* **Shared databases** — access granted by another owner, shown with your effective access role

## PgBouncer

Every database connection goes through [PgBouncer](https://www.pgbouncer.org/), a lightweight connection pooler. This means:

* **Lower overhead** — PgBouncer multiplexes many client connections onto fewer PostgreSQL backend connections
* **Port 6432** — Always connect on port 6432, not 5432
* **Transparent** — Your application connects to PgBouncer exactly like it would to PostgreSQL directly
* **Network policy enforcement** — per-database IP allowlists are applied at the PgBouncer layer
* **Lifecycle coordination** — start, stop, restart, and password resets flow through PgBouncer as well as PostgreSQL

## Backups

Backups use `pg_dump` piped through `gzip`. In production, DBHost stores durable backups off-host in AWS S3 `eu-north-1` as `.sql.gz` files, while the VPS only keeps temporary working files during backup creation. DBHost runs a daily scheduled backup job at `02:00 UTC`, keeps 30 days of backups in production, and also lets authorized roles trigger backups manually from the dashboard or API.

Backup files are named with UTC timestamps: `20260319_120000.sql.gz`.
Internal/system databases are excluded from the scheduled run. Dashboard
on-demand backups are available on every plan; API and CLI triggers require Pro
or Business.

The verified backup created for database deletion is an explicit exception to
normal 30-day retention. It remains available for the seven-day deleted
database recovery window and is permanently removed, including all S3 object
versions, when that tombstone is purged.

Environment tags, operation status, pending invitations and customer webhooks
are generally available. Restore/import and clone remain exact-target
rollouts. Customer deletion and recovery use a separate managed-tenant
lifecycle gate and still require owner authorization, an exact
database/operation/registry/OID binding and the agent capability. Automatic
purge has its own default-off gate and accepts only expired operation-bound
tombstones. A feature flag alone never authorizes a target.

## User identity

DBHost treats one verified primary email as one logical account.

If Clerk issues a new user ID for the same verified primary email, DBHost reclaims the account instead of creating a second local user record. Databases, API keys, and subscriptions move to the new identity automatically. Historical audit-log actor IDs are preserved.

## API keys

Pro and Business users can create API keys for programmatic access to the
DBHost REST API. Each key has:

* A **prefix** (visible, for identification)
* A **hashed secret** (stored securely, shown only once when created or replaced)
* A **label** (your description)
* A **scope mode** (`all` or `selected`, shown in the UI as `Full account access` or `Selected databases`)
* **Last used** timestamp

Use API keys with the `Authorization: Bearer <key>` header.

Selected-database keys only list and operate on the databases assigned to them. Full-account keys can create and manage every database in the owning account.

## Security boundaries

DBHost hardens the path between the dashboard and the VPS agent in a few specific ways:

* **Stored tenant database passwords are encrypted at rest** in the control-plane database
* **The in-dashboard SQL Explorer is owner-only and read-only**, and runs through a dedicated PostgreSQL explorer role
* **Customer-facing agent routes only operate on managed databases** present in the local agent registry, so internal databases such as `dbhost` are outside that route surface
* **Public API routes and the internal agent enforce request budgets and request-size caps**, which makes direct HTTP abuse and noisy automation harder to sustain

These controls are additive. Direct PostgreSQL connections still use the normal database credentials shown on the detail page, while the explorer keeps its own tighter boundary.

## Database collaboration

Database access has its own role system, separate from the platform-wide `user` / `admin` role.

| Database role | Access                                                                                                                   |
| ------------- | ------------------------------------------------------------------------------------------------------------------------ |
| **owner**     | Full control, including delete, sharing, lifecycle, backups, read-only explorer, credentials, IP allowlist, and activity |
| **admin**     | Manage collaborators, lifecycle, credentials, backups, connection activity, and IP allowlist                             |
| **developer** | View credentials and view/download backups; cannot trigger, restore, upload, or delete backups                           |
| **viewer**    | View the detail page and connection activity, but cannot use the explorer, credentials, or write actions                 |

Existing DBHost users receive membership directly. For an unknown email, the
pending-invitation flow stores a local DBHost row and sends a seven-day Clerk
invitation. Acceptance during first sign-in is idempotent; database/role data
is not stored in Clerk public metadata.

## Activity log

Every significant action is recorded in the activity log with:

* **Who** performed the action (user ID)
* **What** action was taken (create, delete, reset\_password, etc.)
* **Which** resource was affected (database name, user ID)
* **When** it happened
* **Details** (JSONB, action-specific context)

Users can review account and database activity in the dashboard. Platform operators have a separate internal audit view for full-platform administration.

## System incidents

Operational failures are tracked separately from actor-driven activity so DBHost can distinguish system health issues from user actions.

This includes:

* render/runtime failures
* public API failures
* agent reachability problems
* backup failures or stale backups
* watchdog-generated health incidents

Platform operators use a private internal admin surface to inspect and manage these incidents.

## Customer operation webhooks

Webhook v1 covers backup events generally. Restore, clone, delete, and recovery
event types are also defined for databases enrolled in those limited rollouts.
Deliveries use a stable event ID and a timestamped
HMAC-SHA256 signature. Secrets are encrypted at rest and shown only at
create/rotate time.

Endpoints must use public HTTPS. DBHost rejects localhost, private/link-local
addresses, unsafe redirects, and DNS-rebinding targets. Deliveries use bounded
retries with jitter and a delivery ledger; permanently failing endpoints can be
disabled automatically.

## Platform roles

DBHost also has two platform-wide roles:

| Role      | Access                                                                                              |
| --------- | --------------------------------------------------------------------------------------------------- |
| **user**  | Own databases, own activity history, own API keys, own settings                                     |
| **admin** | Everything above plus platform administration, moderation, health monitoring, and incident response |
