Docs
Database and Migrations

Database and Migrations

How the schema is changed, where the record of migrations lives, and the rules that keep data safe.

The Record

The database's own migration history (Supabase, Database, Migrations) is the truth; 69 migrations as of 13 Oct 2026. The repository folder supabase/migrations/ holds the files from 18 Aug 2026 onward, named YYYYMMDD_description.sql, each with a header saying when and how it was applied. Tables created before the folder existed have no file; their shape is restated with if not exists in later migrations where it matters.

Adding a Migration

Write the file

supabase/migrations/YYYYMMDD_short_description.sql. Use if not exists and if exists guards so a re-run is harmless. Put a header comment saying what it does and why.

Apply it to production

From the Supabase SQL Editor, or through the Supabase MCP connector in Claude Code. There is no CLI pipeline and no connection string on a developer's machine.

Record it

Add "APPLIED TO PRODUCTION {date}" to the file header, commit it with the code that needs it, and deploy.

Apply before deploying the code, so the new code never meets the old schema.

Rules

  • Row-level security is on with no policies. Access is decided in server code, which uses the service key. Do not add policies expecting them to protect something.
  • Never expose the Supabase URL and a key to a browser. All reads go through server components, all writes through server actions.
  • One business per founder. Never expose legal, contact or NAICS fields on a business to other members.
  • Member free text stays in the platform. Private notes, admin ratings and decline reasons are never sent to Nexus.
  • Constraints are where tracks and options are allowed. A new application track or a new option for a constrained column needs a migration (the partner track was once rejected by a check constraint in production; see the FAQ).

Backups

Supabase takes backups according to the plan. A restore replaces the whole database; take a fresh backup first and prefer querying the backup for a single mistaken change.

Reading Data Safely

The Table Editor and SQL Editor are fine for reading. For a one-off write, prefer a script under scripts/ that uses the admin client, so the change is reviewable and repeatable.

Scripts That Touch Data

ScriptWhat it does
scripts/reseed-profiles.tsRe-fills profiles from application answers, gaps only
scripts/sync-nexus-members.tsBulk sync to Nexus
scripts/set-member-role.tsChange a role (Clerk first, then the database)
scripts/normalize-member-roles.ts, scripts/reconcile-users.mjsOne-off repairs from earlier phases