Configuration

Everything is passed to the breadcrumb() factory.

const bc = breadcrumb({
  database: postgres(process.env.DATABASE_URL!),
  basePath: "/api/breadcrumb",
  environment: process.env.VERCEL_ENV,
  ingest: { apiKey: process.env.BREADCRUMB_KEY },
  authorize: (req) => isAdmin(req),
  pricing: { "gpt-5": { input: 1.25, output: 10, cachedInput: 0.125 } },
  retention: { default: "90d", environments: { development: "7d" } },
  redact: (span) => scrub(span),
  maxPayloadChars: 16384,
  flushMode: "batch",
  migrations: "auto",
});

Options

OptionTypeDescription
databaseDatabaseAdapterRequired. sqlite(path) or postgres(url) from @breadcrumb-sh/core/adapters, or your app’s existing pool.
basePathstringWhere the handler is mounted, and what the dashboard’s api prop must point at. Default "/breadcrumb".
environmentstringStamped on every span. Defaults to VERCEL_ENVNODE_ENV"development".
ingest{ apiKey }Enables the HTTP ingest endpoints for external services (OTLP + JSON). Omit to keep ingest closed.
authorize(req) => boolean | ResponseGuards the query routes. Return true to allow, false for 401, or a Response (e.g. a redirect). The dashboard page is yours to guard.
pricingRecord<string, ModelPrice>Your per-model prices (USD per 1M tokens). Breadcrumb ships no prices — omit and cost stays whatever you set explicitly.
retentionRetentionOptionsPer-environment windows. Bounded sweeps piggyback on ingest; no cron needed.
redact(span) => span | voidScrub PII or trim payloads before storage. Runs on every span from every path.
maxPayloadCharsnumberCaps captured input/output size. Default 16384; 0 disables. The budget is spent on the long strings inside a payload, so a capped message array is still an array of messages.
shouldExport(span: ReadableSpan) => booleanFilters what bc.spanProcessor keeps when registered on your own tracer provider. Default: spans carrying ai.*, gen_ai.*, or breadcrumb.*.
flushMode"batch" | "sync""batch" (default) buffers and exports every ~2s. "sync" exports each span as it ends — for serverless/edge.
migrations"auto" | "manual""auto" (default) creates the schema on first use. "manual" never runs DDL at runtime — you apply migrations yourself. See Migrations.
mcp{ name?, hidePayloads? }Tunes the MCP endpoint your coding agent connects to. Always mounted; unreachable until someone creates a key. See MCP.

Pricing

Breadcrumb never assumes a model’s price. Declare the models you use and cost is computed from token usage, splitting cached-read, cache-write, and reasoning tiers:

pricing: {
  "gpt-5": { input: 1.25, output: 10, cachedInput: 0.125 },
  "claude-sonnet": { input: 3, output: 15, cacheWrite: 3.75 },
}

Keys match as lowercase substrings of the span’s model, longest key wins. See Cost & tokens.

Retention

retention: {
  default: "90d",
  environments: { development: "7d" },
  sweep: "auto", // or "manual" — then call bc.api.runRetention() yourself
}

Durations are "30m", "12h", or "90d". Sweeps are bounded batches that run at most every 15 minutes, coordinated across instances via the database.