Configuration
bunderstack declarations, runtime options, transports, adapters, and lifecycle
Application options
const backend = bunderstack({
schema,
database: {
adapter: libsql(),
url,
authToken,
migrations: './migrations',
},
access,
auth,
authResolver,
storage,
email,
env,
jobs: (j) => j.define({}),
api,
middleware: [instrumentation],
background: { autoStart: true },
rateLimit: { windowMs: 60_000, max: 100 },
idempotency: { ttlMs: 86_400_000 },
realtime: { bufferSize: 1_000, resumeSeconds: 300, redis },
openapi: true,
})
const app = await backend.start()schema and database.adapter are required. All validation slots accept
Standard Schema. api takes your oRPC router — an object built from bases you
declared with defineApi, or a
callback receiving the framework builder. middleware applies oRPC middleware
to every procedure in the graph, generated ones included; see
Middleware. openapi serves the optional projection at
/api/openapi.json. auth takes better-auth options directly, or
a builder ({ db, env }) => BetterAuthConfig when database hooks need the app's
own connection — see Auth.
Realtime transport
| Configuration | Transport | Intended use |
|---|---|---|
omitted or false | disabled | no subscriptions or publications |
realtime: true | memory | one application process |
realtime: true plus REDIS_URL | Redis | separate web and worker processes |
realtime: { redis } | Redis | explicit shared publisher configuration |
bufferSize and resumeSeconds configure Publisher retention. Heartbeats and
exponential reconnect belong to the client transport and require no
application setting.
When a standalone worker uses the memory publisher,
app.runWorker() rejects startup unless
allowProcessLocalRealtime: true is explicit. This prevents silently
publishing events that cannot reach another process.
Database adapters
| Import | Dialect | Optional peer | Typical URL |
|---|---|---|---|
bunderstack/libsql | SQLite | @libsql/client | file:./data.db, libsql://… |
bunderstack/bun-sqlite | SQLite | none | file:./data.db, :memory: |
bunderstack/pglite | Postgres | @electric-sql/pglite | file:./data.pglite, memory:// |
bunderstack/bun-sql | Postgres | none | postgres://… |
bunderstack/postgres-js | Postgres | postgres | postgres://… |
The adapter dialect must match the Drizzle schema. Import only the adapter you use so optional drivers stay outside the application dependency graph.
Email and storage adapters
Email defaults to the console provider in development. Use Resend directly or the optional SMTP adapter:
import { smtp } from 'bunderstack/email-smtp'
email: {
from: 'My app <[email protected]>',
provider: smtp({ url: process.env.SMTP_URL! }),
}Storage may use a local directory or S3-compatible infrastructure. Buckets carry their own upload, access, and image-transform rules; see Storage.
Declaration and lifecycle
await app.close() stops background work and closes application-owned database
and Publisher resources. app.status, app.signal, and
app.backgroundRunning expose lifecycle state.
bunderstack() is synchronous and side-effect-free. Deployment tooling imports
the exported backend and reads backend.manifest without opening database or
Redis connections. backend.start({ env }) owns production runtime resources;
backend.test() creates an isolated, lexically owned test fixture.
For test suites, declare reusable defaults and setup with
backend.test.configure({ env, database, logs, setup }). A call to the returned
factory may override its defaults; env and database are deep-merged. The value
returned from setup is exposed as fixture.context, and
fixture.defer(cleanup) attaches additional resources to the fixture lifecycle.
Common environment variables
| Variable | Purpose |
|---|---|
DATABASE_URL | selected database connection |
DATABASE_AUTH_TOKEN | hosted libSQL authentication |
AUTH_SECRET | Better Auth secret; required in production |
REDIS_URL | shared Publisher for split processes |
RESEND_API_KEY | Resend provider |
SMTP_URL | optional SMTP adapter |
S3_BUCKET, S3_REGION, S3_ENDPOINT | S3-compatible storage |
BUNDERSTACK_ROLE | all, web, or worker |