Database
PostgreSQL with Drizzle ORM — schema generation, raw queries, and transactions.
QUESTPIE uses PostgreSQL with Drizzle ORM. The database schema is generated from your collection and global definitions.
Configuration
export default runtimeConfig({
db: {
url: process.env.DATABASE_URL || "postgres://localhost/myapp",
},
});Cloudflare Workers
Cloudflare Workers still use PostgreSQL for QUESTPIE. Cloudflare does not host a PostgreSQL database for you; Hyperdrive connects Workers to an existing PostgreSQL database and exposes a runtime-only connection string.
Use db.create() so the Drizzle client is created from the generated schema at runtime:
import postgres from "postgres";
import { drizzle } from "drizzle-orm/postgres-js";
db: {
create: async ({ schema }) => {
const { env } = await import("cloudflare:workers");
const sql = postgres(env.HYPERDRIVE.connectionString, {
max: 5,
fetch_types: false,
prepare: true,
});
return {
drizzle: drizzle(sql, { schema }),
close: () => sql.end(),
};
},
}Do not use db: { url } on Workers. That path creates QUESTPIE's default Bun SQL driver and the Cloudflare adapter rejects it.
For questpie migrate:* commands, use a direct PostgreSQL connection from CI or your machine. Hyperdrive is a Worker binding, so it is not available to the Bun CLI unless you explicitly provide a CLI connection string in your config.
Schema Generation
Codegen produces Drizzle table definitions from your collections. Each field maps to a column type:
| Field | Drizzle Column |
|---|---|
f.text() | varchar / text |
f.number() | integer |
f.boolean() | boolean |
f.date() | date |
f.datetime() | timestamp |
f.select() | varchar |
f.json() | jsonb |
f.object() | jsonb |
.array() | jsonb |
f.relation() | varchar (FK) |
Raw Database Access
Access Drizzle directly through the db context:
handler: async ({ db }) => {
const result = await db.execute(sql`
SELECT COUNT(*) as total FROM appointments
WHERE status = 'completed'
`);
return result;
};Indexes
Define indexes on collections:
import { uniqueIndex, index } from "drizzle-orm/pg-core";
.indexes(({ table }) => [
uniqueIndex("posts_slug_unique").on(table.slug),
index("posts_status_idx").on(table.status),
])Related Pages
- Migrations — Schema versioning
- Collections — Data models