Operate in Production
Operate in Production
Infrastructure services — database, auth, storage, email, queue, search, realtime.
QUESTPIE provides pluggable adapters for common infrastructure services. Configure them in runtimeConfig() and access them through the typed context in hooks, routes, and jobs.
Services
| Service | Default Adapter | Description |
|---|---|---|
| Database | PostgreSQL + Drizzle | Primary data store |
| Migrations | Built-in | Schema versioning |
| Authentication | Better Auth | Sessions, providers |
| Storage | FlyDrive (S3/local) | File uploads |
| Nodemailer | Transactional email | |
| Queue | pg-boss | Background jobs |
| Search | PG full-text search | Text search |
| Realtime | pgNotify / Redis Streams | Live updates |
| KV | Redis / in-memory | Key-value store |
| Logger | Pino | Structured logging |
| OpenAPI | @questpie/openapi | API documentation |
| Deployment | Docker | Production setup |
Configuration
All services are configured in your questpie.config.ts:
questpie.config.ts
import { runtimeConfig, pgBossAdapter } from "questpie"
import { adminPlugin } from "@questpie/admin/plugin"
export default runtimeConfig({
app: { url: process.env.APP_URL },
db: { url: process.env.DATABASE_URL },
secret: process.env.BETTER_AUTH_SECRET,
plugins: [adminPlugin()],
queue: { adapter: pgBossAdapter({ connectionString: process.env.DATABASE_URL }) },
storage: { driver: "local", basePath: "./uploads" },
email: { adapter: consoleAdapter() },
})See Config API for the full options reference.
Accessing Services
All services are available through the context in hooks, routes, and jobs:
handler: async ({ db, collections, globals, queue, email, kv, logger, search, storage }) => {
// db — Drizzle database instance
// collections — typed CRUD for all collections
// globals — typed CRUD for all globals
// queue — publish background jobs
// email — send transactional emails
// kv — key-value cache
// logger — structured logging
// search — full-text search
// storage — file operations
}Swappable Adapters
Each service uses an adapter pattern. Swap adapters without changing your application code:
// Development
queue: { adapter: pgBossAdapter({ connectionString: process.env.DATABASE_URL }) }
kv: { adapter: "memory" }
// Production
queue: { adapter: pgBossAdapter({ connectionString: process.env.DATABASE_URL }) }
kv: { adapter: "redis", url: process.env.REDIS_URL }