Migration: Fauna → Postgres
Strategy:
- Progressive migration guarded by Statsig flags per entity (see
lib/flags/index.js) - Dual-read/dual-path via GraphQL context and resolvers; Postgres path uses services with Neon Postgres client and decoded JWT
Switches:
Global:@deprecated - Use per-entity flags insteadfaunaStoppedkill switch if needed- Per-entity:
faunaMigration*flags (vehicles,orders,plans,settings,widgets,payments,invoices,users,user_tenants, etc.)
Context creation (createResolversContext.js):
- Validates tokens via
getTokens - If Postgres enabled + user migration flags, calls
authMiddlewareto create Neon Postgres client, determines tenant/role, and instantiates services viacreateTenantServices - Dataloaders: Postgres loaders when enabled, otherwise Fauna loaders
Data movement:
- Migration scripts under
scripts/fauna-migration/*andfauna*.fsl - Ensure Prisma schema parity and indices
Auth-context note:
- Tenant services inject decoded JWT into the Postgres session via
set_config('request.jwt.claims', ...)(seeTenantBaseService.ts) - No RLS policies are currently defined in the database — access control is enforced at the application layer via
tenantIdfiltering in service methods - If RLS policies are added in the future, verify that
authMiddlewarecorrectly propagates JWT session variables and test enforcement on key tables
Cutover checklist:
- Enable entity flags in lower env, validate reads/writes
- Run backfill/migration scripts
- Verify
authMiddlewareand service-layer JWT propagation works with Neon Postgres client - Switch write path to Postgres-only for the entity
- Monitor via Sentry/Axiom; roll back flags if needed