Quickback Docs
Quickback for Hono API

Neon

Use Neon serverless PostgreSQL with Quickback. Connection modes, RLS policy generation, Neon Authorize setup, Drizzle integration.

Neon provides serverless PostgreSQL that works with Cloudflare Workers via HTTP connections. Choose Neon when you need PostgreSQL features (JSON operators, full-text search, advanced indexing) or want database-level Row Level Security alongside the generated Hono API.

Why Neon

  • Full PostgreSQL — Advanced queries, joins, PostGIS, full-text search
  • Database-level security — RLS policies enforce access even if the API is bypassed
  • Serverless — HTTP connection mode for Cloudflare Workers
  • Neon Authorize — JWT-based RLS via the auth.user_id() function
  • Better Auth integration — Works seamlessly with the Quickback auth provider

Configuration

quickback/quickback.config.ts
import { defineConfig, defineRuntime, defineDatabase, defineAuth } from "@quickback/compiler";

export default defineConfig({
  name: "my-app",
  providers: {
    runtime: defineRuntime("cloudflare"),
    database: defineDatabase("neon", {
      connectionMode: "auto",  // detects runtime
      pooled: true,
    }),
    auth: defineAuth("better-auth"),
  },
});

Connection modes

ModeBest forHow it works
HTTPCloudflare Workers, edge functionsStateless HTTP queries via @neondatabase/serverless
WebSocketNode.js, BunPersistent WebSocket connection for lower latency
Auto (default)Mixed environmentsDetects runtime and picks the best mode

Environment variables

# For Cloudflare Workers
npx wrangler secret put DATABASE_URL
# Paste: postgresql://user:pwd@ep-xxx.region.neon.tech/db?sslmode=require

# For local development (.env)
DATABASE_URL=postgresql://user:pwd@ep-xxx.region.neon.tech/db?sslmode=require

Migrations

Neon uses PostgreSQL migrations, distinct from D1's SQLite migrations:

quickback compile      # generates migrations under quickback/drizzle/
npm run db:migrate     # applies them

Row Level Security

Quickback emits RLS policies from your firewall and access config. The Neon target uses Neon Authorize's auth.user_id() JWT claim function (the Supabase target uses auth.uid() instead — same pattern, different function).

firewall: [
  { field: 'organizationId', equals: 'ctx.activeOrgId' },
]
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);

Helper functions

FunctionPurpose
get_active_org_id()Returns the user's active organization from user_sessions
has_any_role(roles[])Checks if the user has any specified role
has_org_role(role)Checks for a single specific role
is_org_member()Checks org membership
is_owner(owner_id)Checks record ownership

Setting up Neon Authorize

  1. Open Project Settings → Authorize in the Neon console
  2. Add your JWKS URL: https://your-api.example.com/auth/v1/.well-known/jwks.json
  3. The auth.user_id() function will return the authenticated user's ID from the JWT

Generated files

quickback/drizzle/
├── migrations/
│   ├── 0100_create_rls_helpers.sql
│   ├── 0101_create_rls_policies.sql
│   └── 0102_create_indexes.sql
src/
├── db/schema.ts          # Drizzle schema
├── auth/schema.ts        # Better Auth schema
└── lib/neon.ts           # Connection helper

When to choose Neon vs D1

FactorNeonD1
SQL dialectPostgreSQLSQLite
Security modelRLS + application-layerApplication-layer only
Multi-regionBuilt-in replicationSingle region per database
PricingFree tier, then usage-basedFree tier, then usage-based
Best forComplex queries, existing Postgres appsEdge-first, simple schemas

See also

  • D1 — SQLite at the edge
  • Providers — All database provider options
  • Quickback for Supabase — A different Postgres+RLS path that uses Supabase Auth instead of Better Auth

On this page