Packages and integrations
Choose the right better-effect package and keep ownership explicit.
The monorepo is split into small packages. The core stays framework-neutral; integrations and storage drivers are optional and are installed only when an application uses them. Every integration follows the same rule: describe providers with Layers, capture only non-owning capabilities, and keep resource ownership at the composition root.
Core and application boundaries
| Package | Use it for | Public entry points |
|---|---|---|
better-effect | Effect, Layer, Runtime, Scope, Web boundaries and standard services | ., /web, /bun, /hono, /next, /node, /opentelemetry |
better-effect-http | Typed Fetch requests, status unions, retries, auth recovery and streaming | ., /endpoints, /testing, /opentelemetry |
better-effect-schema | Standard Schema classes, codecs, tagged classes and typed failures | ., /zod, /valibot, /arktype |
better-effect-better-auth | Better Auth Services, hooks, plugin middleware and current sessions | ., /hooks, /hono |
better-effect-kysely | Kysely query terminals, transactions and explicit database ownership | . |
The HTTP client consumes Standard Schema values directly. It does not install a
schema provider. Use a better-effect-schema adapter only when an application
needs provider-specific class derivations or helpers.
Durable queues and storage
| Package | Use it for | Ownership and compatibility |
|---|---|---|
better-effect-mq | Queues, immutable Jobs, producer Programs, Layer-first Workers, optional extensions and testing | Storage-neutral; no database connection or driver |
better-effect-mq-outbox | Prepared enqueue records, routes, post-commit stores and publishers | Storage-neutral; delivery is at-least-once |
better-effect-mq-postgres | PostgreSQL JobStore, optional events, schedules, flows and outbox | Caller-owned or config-created PostgreSQL pool |
better-effect-mq-redis | Redis/Valkey JobStore, optional events, schedules and flows | Caller-owned clients or adapter-created connections |
better-effect-mq-mongodb | MongoDB JobStore, optional events, schedules, flows and outbox | Requires transaction-capable MongoDB deployment |
better-effect-mq-sqlite | Embedded SQLite JobStore, optional events, schedules, flows and outbox | One writer; migration and database ownership are explicit |
better-effect-mq-mysql | MySQL/InnoDB JobStore, optional events, schedules, flows and outbox | MySQL 8/InnoDB; migration and pool ownership are explicit |
Read the MQ guide for the storage-neutral contracts, the adapter guides for durable providers, and the outbox guide for post-commit publishing. Driver-specific migrations, connection options and deployment requirements live in each adapter's package README.
Choosing an ownership model
- Use
Layer.succeedfor a caller-owned value that a Runtime must not dispose. - Use a scoped Layer when the Layer creates the resource and should release it with the Runtime root Scope.
- Use an integration's
borrowedor caller-owned form when another Layer owns a shared pool, client or Kysely instance. - Use
NodeRuntime.launchorNodeRuntime.runMainfor a process-owned server root. UseNextEffect.managedonly when Next owns the process lifecycle. - Use
Worker.service(...).layer(...)andOutboxPublisher.service(...).layer(...)for supervised background components; do not start detached loops from an application callback.
Optional peers
The core package does not require Hono, Bun, Next.js, Better Auth, Kysely, OpenTelemetry, database drivers or schema providers. Optional peers belong to the subpath or package that uses them. This keeps a generic consumer small and lets package tarball tests prove that unused integrations are not loaded.
For removed Runtime-first APIs and the exact replacement for each integration, see Layer-first migration.