Neon
Quickback generates PostgreSQL schemas with Row Level Security for Neon. Database-level security with Neon Authorize and Better Auth.
Quickback supports Neon as a PostgreSQL database provider, generating schemas with Row Level Security (RLS) policies that enforce your firewall configuration at the database level.
Why Neon?
- Full PostgreSQL — Advanced queries, joins, PostGIS, full-text search
- Database-Level Security — RLS policies enforce access even if API is bypassed
- Serverless Architecture — HTTP connection mode for Cloudflare Workers
- Neon Authorize — JWT-based RLS with
auth.user_id()function - Better Auth Integration — Works seamlessly with Better Auth
Configuration
import { defineConfig, defineRuntime, defineDatabase, defineAuth } from "@quickback/compiler";
export default defineConfig({
name: "my-app",
providers: {
runtime: defineRuntime("cloudflare"),
database: defineDatabase("neon", {
connectionMode: 'auto', // auto-detects based on runtime
pooled: true,
}),
auth: defineAuth("better-auth"),
},
});Environment Variables
DATABASE_URL=postgresql://user:pwd@ep-xxx.neon.tech/db?sslmode=requireRow Level Security
Quickback generates RLS policies from your firewall config:
firewall: {
organization: {},
owner: { mode: 'optional' }
}-- Generated policy (uses auth.user_id() for Neon)
CREATE POLICY "documents_select" ON documents FOR SELECT
USING (
organization_id = get_active_org_id()
AND (has_any_role(ARRAY['admin']) OR user_id = auth.user_id())
);Firewall Patterns
Organization-Scoped:
CREATE POLICY "projects_select" ON projects FOR SELECT
USING (organization_id = public.get_active_org_id());User-Scoped:
CREATE POLICY "preferences_select" ON preferences FOR SELECT
USING (user_id = auth.user_id());Public Tables:
CREATE POLICY "categories_deny_anon" ON categories FOR ALL TO anon USING (false);
CREATE POLICY "categories_all" ON categories FOR ALL TO authenticated USING (true) WITH CHECK (true);Generated Helper Functions
| Function | Purpose |
|---|---|
get_active_org_id() | Returns user's active organization from user_sessions |
has_any_role(roles[]) | Checks if user has any specified role |
has_org_role(role) | Checks for a specific role |
is_org_member() | Checks org membership |
is_owner(owner_id) | Checks record ownership |
Generated Files
drizzle/
├── migrations/
│ ├── 0100_create_rls_helpers.sql
│ ├── 0101_create_rls_policies.sql
│ └── 0102_create_indexes.sql
src/
├── db/
│ └── schema.ts
├── auth/
│ └── schema.ts
└── lib/
└── neon.tsSetting Up Neon Authorize
- Go to Project Settings > Authorize in Neon console
- Add your JWKS URL:
https://your-api.com/auth/v1/.well-known/jwks.json - The
auth.user_id()function will return the authenticated user's ID from JWT
Getting Started
- Create a Neon project at neon.tech
- Configure your Quickback project for Neon
- Run
quickback compile - Apply migrations with
drizzle-kit migrate