Database Architecture
How Postbase organises its internal tables in the _postbase schema and isolates per-project data.
Database Architecture
Internal Schema: _postbase
All Postbase platform tables live in the _postbase PostgreSQL schema, managed by Drizzle ORM.
organisations— Groups of projectsprojects— Individual Postbase instancesusers— Per-project authenticated userssessions— Refresh token storeprovider_configs— Per-project OAuth provider settingsemail_settings— Per-project SMTP configurationemail_templates— Per-project email templates (magic_link, etc.)storage_buckets— Bucket definitionsstorage_objects— Files within bucketsstorage_connections— Per-project S3/R2/GCS credentialsapi_keys— Anon + service role keys per projectaudit_logs— Action audit trail
Per-Project Schema Isolation
Each project gets its own PostgreSQL schema for user-created tables:
Schema name: proj_<projectId_without_hyphens>
Example: proj_550e8400e29b41d4a716446655440000Isolation Rules
User tables — PostgreSQL schema
proj_<id>Cron jobs — Named
pb_<id>_<jobName>incron.jobMessage queues — Named
pb_<id>_<queueName>in pgmqRLS policies — Scoped to each project's schema tables
ORM Setup
# Generate Drizzle migrations
pnpm drizzle-kit generate
# Push schema directly (dev)
pnpm drizzle-kit pushimport { db } from '@/lib/db'
import { projects, users } from '@/lib/db/schema'
import { eq } from 'drizzle-orm'
const [project] = await db
.select()
.from(projects)
.where(eq(projects.id, projectId))
.limit(1)