browser-native observability databases
OTLP in.
Pixels out.
Every observability SPA today is a dumb terminal—every pan, zoom, and filter round-trips to a backend. o11ykit puts a real columnar database in the browser: sub-4 bytes per point, instant cross-signal correlation, zero GC pressure. No Prometheus. No Elasticsearch. No backend.
primitives
A toolkit, not a platform.
Compose your own observability stack from focused, single-purpose packages. Each does one thing. Each earns its bytes.
ALP + XOR-delta + dictionary encoding. Sub-4 bytes per sample. Columnar compression purpose-built for time-series.
demoDictionary encoding collapses 90%+ of span strings. Typed-array parent-child indices for SIMD-friendly critical-path computation.
demoDrain3-style template extraction collapses string columns 5-10x. Turns unique messages into template_id + params.
sourceOTLP protobuf and JSON decoder. Zero-copy where possible. Streams directly into o11y*db columnar format.
docsStatistical benchmarking harness. If a stat appears in copy, the demo proves it live. Regression detection built in.
benchmarkscorrelation
Three signals. One window. Zero network.
All three stores co-resident in memory. Brush a metric spike, get matching traces and logs in the same frame. No server round-trips. No credentials. No loading spinners.
// 1. Brush a time range in tsdb const window = tsdb.query({ start: brushStart, end: brushEnd, metric: "http.duration" }); // 2. Correlate: pass to traces + logs const spans = tracesdb.query({ start: window.start, end: window.end }); const logs = logsdb.query({ traceIds: spans.traceIds }); // 3. Render: zero network calls chart.update(window.points); waterfall.update(spans); logTable.update(logs);
How it works
Brush a spike in your metric chart. tsdb returns the matching time window as typed arrays.
Pass the window to tracesdb and logsdb in local memory. Dictionary-encoded lookups, zero serialization.
Render all three panels in the same animation frame. Total latency: 0 ms network, sub-ms compute.
boundaries
Six things this isn't.
Clear boundaries prevent scope creep. o11ykit sits after your backend, inside the UI. Limits are a feature.
Not Prometheus
We don't scrape, store long-term, or serve remote queries. We consume what Prometheus produces.
Not Elasticsearch
We don't do distributed full-text search. We do template-aware log compression in a single tab.
Not Grafana
We're a library, not a dashboard. We output typed arrays—what you render is your business.
Not OTel SDK
We don't instrument your code. We store and query what your instrumentation produces.
Not DuckDB
DuckDB-WASM is 18 MB with no metric semantics. We're <5 KB with deep signal awareness.
Not a backend
Single-user, single-tab, in-process. Complements your server-side store, never replaces it.
manifesto
The browser is no longer a thin client. It has 8 GB, six cores, and SIMD. We should stop treating it like a 1996 terminal and put a real database in there.