Browse documentation

Route group: /p/:id/database/* (index redirects to functions). Source: apps/studio/src/features/database.

Functions

GET /admin/schema/functions and friends via functions.api.ts. Lists Postgres functions with their return types, and is the source for the function picker used by the trigger editor.

Triggers

triggers.api.ts manages real Postgres triggers (CREATE TRIGGER … EXECUTE FUNCTION …). TriggerEditorModal composes table and function references (TriggerTableRef, TriggerFnRef) into a statement. Full semantics: Postgres triggers.

Extensions

extensions.api.ts lists installed and available extensions and installs one — e.g. POST /admin/schema/extensions/pg_cron, which the cron screen calls when the extension is missing.

Publications

/p/:id/database/publications, GET/POST /admin/database/publications, PATCH/DELETE /admin/database/publications/:name.

A publication is a list: these tables (or every table), these kinds of change (insert, update, delete, truncate). It sends nothing by itself. A subscriber (another Postgres, Debezium, a warehouse loader) connects to the database over a replication connection, names the publication, and from then on receives every change it covers as it commits. New publication takes the name, the changes and the tables in one step. Each publication's Connect button shows the subscriber side: whether Postgres is reachable from outside (and where to publish a port if not, under Project Settings → Database access), the role, and a ready CREATE SUBSCRIPTION … PUBLICATION <name> statement. A banner warns when wal_level is not logical, in which case publications are defined but stream nothing until Postgres restarts with it.

Publications do not drive Motherbase Realtime: which tables broadcast is chosen under Realtime.

Column privileges

/p/:id/database/column-privileges, GET/PUT /admin/database/column-privileges.

RLS policies decide which rows a role reaches; column privileges decide which columns of those rows. Pick a table and a role (anon = no signed-in user, authenticated = a signed-in user, service_role = the secret key, which skips RLS but not these grants), then uncheck what the role must not touch. SELECT reads the column, INSERT gives it a value on a new row, UPDATE changes it, REFERENCES lets a foreign key point at it. The page lists the columns the role cannot read. When the role holds a privilege on the whole table, unchecking one column replaces that grant with one on every other column, the only way Postgres can hide a single column.

Postgres enforces it: a REST request that names a column the role may not read is refused, and so is select=*, which expands to every column. Clients of a table with hidden columns select the columns they need.

Settings

/p/:id/database/settings:

  • Connection: how the API reaches Postgres and whether a port is published.
  • SQL editor (database.sqlEditor): whether the SQL editor may write. On by default; off, every statement runs in a READ ONLY transaction. See SQL editor.
  • Configuration: the Postgres parameters worth tuning, GET/PATCH /admin/database/config, the same list as motherbase postgres-config.

Migrations

Studio-authored, reviewed migrations backed by the SchemaMigration table. Migrations can also arrive from a connected GitHub repository — see Git Migrations.

ActionEndpoint
ListGET /admin/migrations
DetailGET /admin/migrations/:id
Diff against live schemaGET /admin/migrations/diff
CreatePOST /admin/migrations with { name, upSql, downSql? }
ApplyPOST /admin/migrations/:id/apply
Roll backPOST /admin/migrations/:id/rollback

NewMigrationModal drafts the SQL, MigrationDiffModal shows drift, MigrationDetailModal shows the stored statements, MigrationStatusBadge renders pending / applied / rolledback. A checksum of upSql detects edits made after creation. See the data model.

An empty downSql is sent as undefined rather than an empty string — a migration is either reversible or explicitly not.

Backups

ActionEndpoint
ListGET /admin/backups/list
Read schedule configGET /admin/backups/config
Save schedule configPUT /admin/backups/config
Run nowPOST /admin/backups/run
RestorePOST /admin/backups/restore

Restore takes either a local file ({ file }) or an offsite object ({ key }), plus confirm: 'RESTORE'. RestoreModal is what collects that confirmation.

Warning

Restoring replaces the project's database contents. The confirmation string is required by the API itself, not just the UI, so an accidental API call cannot trigger it.

Schedule, retention and offsite settings live in the backup.schedule settings group; see backups and restore.

Webhooks

webhooks.api.ts manages Webhook rows and their events[], and can send a test delivery returning { ok, status, ms }. WebhookDrawer shows recent WebhookDelivery rows. Matching rules and payloads: Events & webhooks.

Cron

Two kinds of recurring work on one screen:

KindEndpoints
pg_cron jobsGET /admin/cron/pg/jobs, POST /admin/cron/pg/jobs, PATCH /admin/cron/pg/jobs/:jobid (active), DELETE /admin/cron/pg/jobs/:jobid, GET /admin/cron/pg/jobs/:jobid/runs
Application jobsGET /admin/cron/app/jobs

The pg_cron listing returns extensionMissing, and the screen offers to install the extension (POST /admin/schema/extensions/pg_cron) instead of failing. CronRunDrawer shows run history with JobStatusIcon. See cron jobs.

Realtime

realtime.api.ts reads and writes the realtime config (GET/PATCH /admin/realtime/config, plus the respect-rls toggle) and lists channels, events and presence. RealtimeConfigPanel is the editor. See Realtime.

RLS access matrix

The Studio screen is Authentication → Role Access (/p/:id/auth/access). It shows, per table, what anon and authenticated can read, insert, update and delete according to the real PostgreSQL policies and grants. It is a read-only view; it does not execute arbitrary SQL and does not change policies.

The query simulator still exists as an operator/automation capability, but is not a Studio page. The CLI and MCP expose it through the admin API:

POST /admin/rls/simulate       { sql, ...caller, limit }
POST /admin/rls/simulate/diff  { sql, left, right }

It runs a query as a chosen caller and always rolls the transaction back. See the RLS guide and MCP Server for the CLI/MCP workflow.