Skip to main content
Causeloop uses PostgreSQL 16 with Row-Level Security (RLS) as the primary tenant isolation mechanism. When 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

For Neon:
2

Load schema, seed data, and functions

3

Apply migrations

Migrations are numbered SQL files in db/migrations/ and are applied in order. The script is idempotent — it tracks applied migrations and skips already-applied ones.

Migrations

The db/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

This is the most critical database security step. The Postgres superuser bypasses Row-Level Security. If your application connects as the superuser (or as neondb_owner on Neon, which has BYPASSRLS), every RLS policy is silently ignored and tenant data is not isolated.Always connect the application as a dedicated non-superuser role.
Causeloop requires two database roles:

Create the application role

Then connect your application as 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:
The 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 default neondb_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:
Key tables by category:

Backup and restore

The built-in backup approach uses pg_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.
For Neon, point-in-time restore is available through the Neon console without needing manual pg_dump jobs.