Trovella Wiki

Query Patterns

How database queries are structured, scoped, and executed across the Trovella codebase.

All tenant-scoped data access in Trovella flows through a single function: withTenantContext. This topic explains what that function does, how the tRPC procedure chain builds the context around it, and what patterns you should follow when writing queries.

Core Principle

The bare database connection (db) runs as the PostgreSQL superuser and bypasses RLS. Tenant-scoped queries must always run inside withTenantContext, which opens a transaction, sets session variables, and switches to the authenticated role so that RLS policies filter every row.

For the RLS policies themselves and the CASL permission model, see Identity & Access -- Tenant Isolation.

Two Paths to the Database

PathImportRLS ActiveUse When
Tenant-scopedwithTenantContext from @repo/dbYesAny query touching tenant data
Bare connectiondb from @repo/db/clientNoMigrations, seeds, auth bootstrap, health checks

The package enforces this split at the export level. @repo/db does not export db -- you must explicitly import from @repo/db/client to get the bare connection, which makes the intent visible in code review.

How a Typical Request Flows

Browser request
  -> tRPC handler
    -> protectedProcedure   (validates session)
    -> tenantProcedure       (calls withTenantContext, injects ctx.db)
    -> authorizedProcedure   (looks up member, builds CASL ability)
    -> router handler        (uses ctx.db for all queries)

The ctx.db provided to router handlers is the transaction object from withTenantContext. RLS is active on every query through this object. You do not need to add WHERE organization_id = ... filters manually -- the database enforces it.

Pages in This Topic

PageWhat It Covers
Tenant ContextwithTenantContext internals -- session variables, transaction scope, type signature
Connection ManagementPool configuration, import paths, the Database and Transaction types
Procedure ChainHow tenantProcedure and authorizedProcedure build query context in tRPC
Drizzle PatternsCommon query patterns: select, insert, update, delete, raw SQL, relations
PerformanceinitPlan caching, parallel queries, pagination, aggregation
Non-Tenant QueriesWhen bare db is appropriate and how to use it safely

On this page