DATABASE_URL is not set the app runs with an in-memory store — suitable for development and demos. Set DATABASE_URL when you want persistent data.
Supported databases
Database files
Applying the schema
1
Set DATABASE_URL
2
Load schema, seed data, and functions
3
Apply migrations
db/migrations/ and are applied in order. The script is idempotent — it tracks applied migrations and skips already-applied ones.Migrations
Thedb/migrations/ directory contains forward-only numbered migrations. Do not modify existing migration files after they have been applied.
Apply all migrations after the initial schema load:
RLS two-role model
Causeloop requires two database roles:Create the application role
causeloop_app:
How RLS works
RLS policies use a session-local GUC (app.current_workspace) that the application sets at the start of each request:
app_current_tenant() function reads this GUC, and every tenant table has four policies:
FORCE ROW LEVEL SECURITY means even the table owner is subject to policies in the causeloop_app session (though not in a superuser session — which is why the non-superuser role is essential).
Neon-specific note
On Neon, the defaultneondb_owner role has BYPASSRLS. Do not use neondb_owner in DATABASE_URL. Create a separate causeloop_app role as above and use that connection string instead.
Schema conventions
Causeloop’s schema follows consistent conventions:Entity overview
The core tenancy model:Backup and restore
The built-in backup approach usespg_dump:
Automated backup verification (scheduled backup + restore test + checksum validation) is on the SOC 2 roadmap but not yet implemented. Until then, run and verify backups manually on a schedule. See SOC 2 readiness for the current gap status.
pg_dump jobs.