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.
Infrastructure Services
These are framework-level infrastructure services configured in runtimeConfig(). They are different from user-defined Services, which wrap application-specific business logic and live under ctx.services.* by default.
| 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 |
Cloudflare Workers are supported through the explicit questpie/adapters/cloudflare entrypoint. A Cloudflare deploy must configure Hyperdrive-backed PostgreSQL, R2/S3 storage, Workers KV, Cloudflare Queues, and Durable Object realtime adapters; QUESTPIE does not fall back to Node/Bun defaults on Workers.
Configuration
All services are configured in your questpie.config.ts:
import { runtimeConfig } from "questpie/app";
import { ConsoleAdapter } from "questpie/adapters/console";
import { pgBossAdapter } from "questpie/adapters/pg-boss";
export default runtimeConfig({
app: { url: process.env.APP_URL },
db: { url: process.env.DATABASE_URL },
secret: process.env.BETTER_AUTH_SECRET,
queue: {
adapter: pgBossAdapter({ connectionString: process.env.DATABASE_URL }),
},
storage: { location: "./uploads", basePath: "/api" },
email: { adapter: new 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: { defaultTtl: 3600 }
// Production
queue: { adapter: pgBossAdapter({ connectionString: process.env.DATABASE_URL }) }
kv: { adapter: myKvAdapter, defaultTtl: 3600 }