LogbunConfig.mode is 'volatile' (default) or 'durable'.
Volatile
The root constructs an internal MemoryReliabilityAdapter when reliability is omitted. persistent is always false. Unflushed queues, the optional in-process journal, and the memory DLQ are lost on process exit.
Volatile mode emits limit / unsafe_default_volatile once at construction (including when you set mode: 'volatile' explicitly).
On request-scoped hosts (Workers, serverless), detached fire() is not a delivery guarantee. Use:
await audit.fireAsync('user.created', { actorId: 'u1' });
await audit.flush();Durable
Durable mode requires a reliability adapter with persistent: true. Missing reliability or MemoryReliabilityAdapter throws synchronously in the constructor:
durable mode requires LogbunConfig.reliability with a persistent adapter
(e.g. FileReliabilityAdapter from "logbun/durability/filesystem" or
CloudflareReliabilityAdapter from "logbun/durability/cloudflare")durable mode requires a persistent ReliabilityAdapter
(MemoryReliabilityAdapter is not durable)ENTERPRISE_DEFAULTS is only { mode: 'durable', requireTenantId: true }. Spreading it without a persistent reliability still throws.
Persistent backends:
| Adapter | Import | Survives |
|---|---|---|
FileReliabilityAdapter |
logbun/durability/filesystem |
Process death, if the disk is intact |
CloudflareReliabilityAdapter |
logbun/durability/cloudflare |
Isolate exit, inside a SQLite Durable Object |
Pre-ready buffer
audit.ready is a bootstrap promise. It never rejects. Failure sets degraded and emits bootstrap_fail / degraded.
Logs accepted before ready sit in a volatile buffer (maxPreReadyBuffer, default 10_000) even when mode: 'durable'. Excess emits drop / pre_ready_buffer_full. Durable-mode pre-ready accepts also emit limit / pre_ready_volatile.
Await ready before fire / fireAsync in durable mode. Bootstrap drains the buffer through the real enqueue path (including journal) before ready resolves.
fire vs fireAsync
fire() |
fireAsync() |
|
|---|---|---|
| Throws | never | yes |
| Returns | void |
Promise<void> |
| Durable admission | background; pass waitUntil on Workers |
awaited |
| Missing tenant when required | drop / require_tenant_id |
rejects |
Oversize tenantId |
drop / max_tenant_id_bytes |
rejects |
| Degraded | drop / degraded |
rejects AuditLogger is degraded — fireAsync unavailable |
If a Cloudflare journal/DLQ row commits but getAlarm / setAlarm fails, fireAsync rejects with DurableAdmissionSchedulingError and durableAdmissionCommitted === true. Do not resubmit that event; call requestMaintenance() after the scheduler recovers. fire() rethrows that error into the waitUntil task (and emits flush_fail / durable_admission_scheduling) so Workers keep the isolate awake; fire() itself still does not throw.
import { isDurableAdmissionSchedulingError } from 'logbun';
try {
await audit.fireAsync('audit.event', input);
} catch (error) {
if (isDurableAdmissionSchedulingError(error)) {
await reliability.requestMaintenance();
} else {
throw error;
}
}isDurableAdmissionSchedulingError accepts the class instance or a duck type with name === 'DurableAdmissionSchedulingError' and durableAdmissionCommitted === true. A lone { durableAdmissionCommitted: true } is not this error.
Degraded
After bootstrap failure, audit.degraded is true. fire drops; fireAsync, query, DLQ ops, flush, and maintenance throw AuditLogger is not initialized (or the fireAsync degraded message). Open a new logger to recover.