Example schema: import { sql } from "drizzle-orm"; import { authenticatedRole } from "drizzle-orm/neon"; import { pgPolicy, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core"; export const clients = pgTable( "clients", { id: uuid("id").primaryKey().defaultRandom(), name: text("name").notNull(), domain: text("domain").unique(), slug: text("slug").notNull().unique(), logoUrl: text("logo_url"), pimsType: text("pims_type"), status: text("status").notNull().default("active"), createdAt: timestamp("created_at").notNull().defaultNow(), updatedAt: timestamp("updated_at").notNull().defaultNow(), }, (table) => ({ // Row-Level Security Policies for Multi-Tenant Isolation // Note: super_admin bypasses RLS (uses dbAdmin connection) // Policy 1: client_admin and practice roles can read their client clientReadPolicy: pgPolicy("clients_client_read", { for: "select", to: authenticatedRole, using: sql`( auth.session()->>'app_role' IN ('client_admin', 'practice_manager', 'practice_viewer') AND ${table.id}::text = auth.session()->>'clientId' )`, }), // Policy 2: client_admin can update their client clientAdminUpdatePolicy: pgPolicy("clients_client_admin_update", { for: "update", to: authenticatedRole, using: sql`( auth.session()->>'app_role' = 'client_admin' AND ${table.id}::text = auth.session()->>'clientId' )`, withCheck: sql`( auth.session()->>'app_role' = 'client_admin' AND ${table.id}::text = auth.session()->>'clientId' )`, }), }) ); export type Client = typeof clients.$inferSelect; export type NewClient = typeof clients.$inferInsert; How I'm how creating the database connection with JWT: import { neon } from "@neondatabase/serverless"; import { drizzle } from "drizzle-orm/neon-http"; const signedJwt = await signNeonJwt({ /* claims */ }); // @ts-expect-error - authToken is supported but not in types const sql = neon(DATABASE_URL_RLS, { authToken: signedJwt }); const db = drizzle(sql, { schema }); current user is neondb_owner, but jwt_claims is empty when I run this query: SELECT current_user, current_setting('request.jwt.claims', true) AS jwt_claims; SELECT tablename, rowsecurity FROM pg_tables WHERE schemaname = 'public' AND tablename = 'clients'; returns clients and t JWT claims structure { "sub": "user-id", "role": "authenticated", "app_role": "client_admin", "clientId": "client-uuid", "iss": "https://portal.mysite.com", "aud": "mysite-app" } Drizzle config excerpt: export default defineConfig({ // ... other config entities: { roles: { provider: "neon", exclude: ["postgres", "neondb_owner"], }, }, }); More debugging info: { "environment": { "hasDatabaseUrlRls": true, "databaseUrlRlsHost": "instance.c-3.us-east-1.aws.neon.tech", "databaseUrlRlsRole": "authenticator", "jwtIssuer": "https://portal.mysite.com", "jwtAudience": "mysite-app", "hasPrivateKey": true, "hasKidEnvVar": true }, "jwt": { "kid": "mysite-2026-01", "issuer": "https://portal.mysite.com", "audience": "mysite-app", "decodedClaims": { "sub": "a8fd1313-3f82-47af-81fe-a444f37c8038", "role": "authenticated", "app_role": "client_admin", "clientId": "27811410-64f4-4910-af60-a21cf7d150ac", "practiceIds": null, "email": "myemail@gmail.com", "name": "First Last", "iat": 1768023207, "iss": "https://portal.mysite.com", "aud": "mysite-app", "exp": 1768026807 }, "tokenLength": 826 }, "jwks": { "accessible": true, "status": 200, "url": "https://portal.mysite.com/.well-known/jwks.json", "hasKeys": true, "keyCount": 1, "firstKeyKid": "mysite-2026-01", "kidMatches": true }, "connection": { "currentUser": "authenticator", "sessionUser": "authenticator", "jwtClaims": "", "jwtClaimsEmpty": true }, "diagnosis": { "usingAuthToken": true, "neonParsingJwt": false, "expectedRole": "authenticated", "actualRole": "authenticator", "roleMatches": false }, "troubleshooting": { "checks": { "jwtGeneration": "✓ JWT generated successfully", "kidMatches": "✓ kid matches JWKS", "jwksAccessible": "✓ JWKS endpoint accessible", "neonParsing": "✗ Neon NOT parsing JWT" } } }