Database: paldocs (Shared CNPG, Schema Ownership, Dual Migrations)

arch-rails-db Architecture

architecture

Database: paldocs

How paldocs (Rails 8) and pal-e-api (FastAPI) share the same CNPG PostgreSQL cluster, with separate migration ownership.

Diagram

Components

Component Purpose Notes
CNPG Cluster (pal-e-postgres) Managed PostgreSQL 17.4 Defined in <code>pal-e-services/terraform/cnpg.tf</code>. Single instance, 5Gi local-path, <code>postgres</code> namespace. Superuser access enabled.
paledocs database Shared database for both apps Created by CNPG <code>bootstrap.initdb</code> (only runs on cluster creation). Owner: <code>paledocs</code> user. Credentials in <code>paledocs-db-credentials</code> k8s secret.
Alembic (pal-e-api) Migrations for original schema Owns: notes, blocks, tags, projects, links, boards, revisions, embeddings (24 migrations). SQLAlchemy 2.0 models.
ActiveRecord (paldocs) Migrations for Rails-specific tables Owns: sprints, Solid Queue tables, any new Rails models. Schema bootstrapped via pg_dump to structure.sql.
Barman backups WAL archiving + scheduled backups Continuous WAL to MinIO (<code>s3://postgres-wal/</code>), gzip compressed. Daily full backup at 02:00 UTC. 7-day retention.
NetworkPolicy Postgres namespace ingress control Paldocs is already in the postgres allowlist alongside pal-e-docs, pal-enterprises, landscaping-assistant, palinks, and others.

Key Decisions

  • Shared database, not separate databases: Paldocs reads and writes the same notes/blocks/boards tables as pal-e-api. This avoids data sync between two databases and lets both apps operate on the same source of truth.
  • Schema ownership transfer via pg_dump: When Rails was introduced, the existing schema was exported via pg_dump, loaded as Rails' db/structure.sql, and Rails' first migration was a no-op stamp. This gave Rails a complete picture without re-running Alembic migrations.
  • Alembic owns pal-e-api columns: Schema changes touching notes, blocks, boards, or other pal-e-api models must go through Alembic in the pal-e-api repo. Paldocs must not create Rails migrations for these tables.
  • Rails owns its own tables: New tables used only by paldocs (sprints, Solid Queue, etc.) get Rails migrations in the paldocs repo.
  • Cross-cutting changes require ordered deploys: If a change touches both codebases, the Alembic migration deploys first (pal-e-api), then the Rails migration follows (paldocs). Order matters.
  • Not in service_databases map: Paldocs uses the CNPG bootstrap database (paledocs), not a dynamically provisioned database from databases.tf. If paldocs needs additional databases (Solid Queue, Action Cable), they would be added to service_databases.
  • arch-k8s -- Deployment overlay where DATABASE_URL is wired
  • arch-keycloak-paldocs -- Auth tables may require cross-cutting schema work
  • paldocs #27 -- Visibility column (cross-cutting: Alembic migration in pal-e-api, not a Rails migration)
  • pal-e-services/terraform/cnpg.tf -- CNPG cluster definition
  • pal-e-services/terraform/databases.tf -- Per-service database provisioning (for_each on service_databases)
  • pal-e-platform/terraform/network-policies.tf -- Postgres namespace ingress rules