---
title: "Configuration"
description: "Every LogbunConfig option, default, and constructor validation rule."
---

> Documentation Index
> Fetch the complete documentation index at: https://logbun-docs.abshahin.workers.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

```ts
import { AuditLogger, ENTERPRISE_DEFAULTS, type IAdapter } from 'logbun';
import { FileReliabilityAdapter } from 'logbun/durability/filesystem';

declare const destination: IAdapter;

const audit = new AuditLogger({
  ...ENTERPRISE_DEFAULTS, // mode: 'durable', requireTenantId: true
  namespace: 'api-replica-1',
  reliability: new FileReliabilityAdapter({
namespace: 'api-replica-1',
dataDir: '.logbun',
wal: { fsync: true },
dlq: { fsync: true, maxEntries: 10_000 },
maxWalBytes: 64 * 1024 * 1024,
encryptionKey: process.env.LOGBUN_ENCRYPTION_KEY,
  }),
  adapter: destination,
  requireTenantId: true,
  batching: {
maxSize: 50,
flushInterval: 2_000,
maxQueueSize: 2_000,
onQueueFull: 'dlq',
  },
  retry: {
insertMaxRetries: 3,
insertBaseDelayMs: 1_000,
maxScanAttempts: 10,
  },
  retention: { days: 365 },
});
```

`ENTERPRISE_DEFAULTS` is only `{ mode: 'durable', requireTenantId: true }`. Durable mode still requires a persistent `reliability` adapter.

## Core

| Option | Default | Meaning |
|---|---:|---|
| `namespace` | required | Logger namespace: `[a-zA-Z0-9_-]{1,64}`, validated at bootstrap. **Not** the WAL/DLQ path. |
| `mode` | `volatile` | `durable` requires `reliability.persistent === true` synchronously. Volatile emits `limit` / `unsafe_default_volatile`. |
| `reliability` | memory in volatile mode | Journal + DLQ backend |
| `adapter` | required | Destination `IAdapter` |
| `onEvent` | — | Observability hook. Listener throws are swallowed. |

## Tenancy and pooling

| Option | Default | Meaning |
|---|---:|---|
| `tenancy.mode` | `single_database` when omitted | `database_per_tenant` forces `requireTenantId` and requires `adapterFactory` |
| `tenancy.resolveConnection` | — | Returns per-tenant connection config for `adapterFactory` |
| `tenancy.knownTenantIds` | — | Extra tenant ids visited by retention prune in `database_per_tenant` |
| `adapterFactory` | — | Recreates per-tenant adapters from `resolveConnection` config |
| `pool.maxActiveConnections` | 50 | LRU pool size. Exhaustion throws `pool_exhausted`. |
| `requireTenantId` | false | Forced true when `database_per_tenant`. When left false (and not DPT), emits `limit` / `unsafe_default_require_tenant`. |

## Batching and retry

| Option | Default | Meaning |
|---|---:|---|
| `batching.maxSize` | 100 | Maximum insert batch size |
| `batching.flushInterval` | 5_000 ms | Short-lived batching timer; not retry scheduling |
| `batching.maxQueueSize` | 1_000 | Per-tenant RAM queue cap |
| `batching.onQueueFull` | `dlq` | `drop` is rejected for durable mode |
| `retry.insertMaxRetries` | 3 | **Total** `bulkInsert` attempts per destination insertion (includes the first try) |
| `retry.insertBaseDelayMs` | 1_000 | Base backoff; doubles each retry |
| `retry.maxScanAttempts` | 10 | Failed DLQ scans before a batch becomes dead |

Durable + `onQueueFull: 'drop'` throws:

```text
Configuration error: onQueueFull="drop" is not valid with mode="durable".
Use "dlq" to prevent data loss, or switch to mode="volatile" for drop behavior.
```

## Caps and safety

| Option | Default | Meaning |
|---|---:|---|
| `maxActiveTenants` | 10_000 | Max concurrent RAM queue keys. Durable: excess tenant keys go to DLQ. Volatile: drop. |
| `maxTotalQueued` | 50_000 | Sum of all per-tenant queue lengths + reservations |
| `maxFlushConcurrency` | 16 | Global bulkInsert semaphore (minimum 1) |
| `flushTimeoutMs` | 30_000 | Overall flush / shutdown deadline |
| `maxQueryLimit` | 500 | Hard cap on `query()` page size. Omitted caller `limit` defaults to **50**, then clamped to `[1, maxQueryLimit]`. |
| `maxPayloadBytes` | 64_000 | Serialized `oldValues`/`newValues`/`metadata` cap. Oversize shrinks by dropping metadata, then oldValues, then newValues, then `{_truncated:true}` placeholders. Emits `truncated`. |
| `maxStringFieldBytes` | 2_048 | UTF-8 cap for `actorId`, `action`, `entityId`, `userAgent`, `ipAddress` (truncated). Never applied to `tenantId`. |
| `maxTenantIdBytes` | 256 | Hard UTF-8 cap on `tenantId`. Oversized ids are dropped or rejected — never truncated. |
| `maxPreReadyBuffer` | 10_000 | Volatile buffer before `ready`. Excess emits `drop` / `pre_ready_buffer_full`. |
| `maxRecoveryBatch` | max queue size | Bound on a journal recovery wave. Floored at 1; `0` does not disable recovery. |
| `integrityChain` | false | Per-tenant SHA-256 chain. Detection only. |
| `redactPaths` | — | Deep paths removed before persistence. Bare keys also delete inside `oldValues` / `newValues` / `metadata`. Root identity fields are never deleted. |
| `retention.days` | — | Finite integer `>= 1`. Pruned only by `runMaintenance()`. |

Removed in 1.0: `RetentionConfig.cronExpression`, `RetryConfig.scanIntervalMs`, `RetryConfig.initialDelayMs`. Filesystem options (`dataDir`, `wal`, `encryptionKey`, …) live on `FileReliabilityAdapter`, not `LogbunConfig`.

Source: https://logbun-docs.abshahin.workers.dev/reference/configuration/index.mdx
