Data model
PulsusDB separates signals because their query shapes differ. Logs, metrics, traces, and profiles use different tables, sort keys, indexes, and aggregation strategies.
Shared principles
Section titled “Shared principles”Canonical labels
Section titled “Canonical labels”Labels are normalized into a stable order before hashing. A canonical label set gives the same fingerprint regardless of the input field order, which is essential for series lookup, stream grouping, and retry handling.
Fingerprints
Section titled “Fingerprints”Metrics series and log streams receive stable fingerprints derived from their canonical identities. Index tables map label matchers to bounded fingerprint sets, allowing the reader to prune data before scanning samples.
Time first
Section titled “Time first”Every query is bounded by a time interval. Generated SQL pushes those bounds into PREWHERE so ClickHouse can use table ordering and partition pruning early.
Metrics
Section titled “Metrics”Metrics use separate metadata/index and sample paths. Raw values retain source timestamps. Rollup levels are built from raw data and from progressively coarser levels; the reader chooses a level only when it can preserve the requested PromQL result.
Native and classic histogram support has dedicated schema and query considerations. OTLP exponential histograms can be translated to classic bucket, sum, and count series until the native path is appropriate.
Log storage separates stream identity from entries. Stream selectors resolve fingerprints through label indexes, then time and line filters operate on the selected rows. Message bodies carry ClickHouse text/skip indexes so indexable searches can avoid brute-force scans.
Per-entry structured metadata is kept distinct from stream labels. Optional ingest-time log-level and pattern extraction add queryable fields without changing the stream identity.
Traces
Section titled “Traces”Spans are ordered and indexed for the way engineers search: service, time, duration, status, and selected attributes. Trace fetch by ID and search by attributes are different read paths.
PULSUS_TRACEQL_INDEXED_ATTRIBUTES can add bloom-filter indexes for selected span or event attributes. Changing the list requires a schema rebuild.
Profiles
Section titled “Profiles”Profiles use profile metadata plus sample/call-tree data. OTLP profiles remain an experimental signal, so profile API and schema surfaces are more likely to change than logs or metrics.
Retention
Section titled “Retention”Retention is a schema property, not a per-request override. PULSUS_RETENTION_DAYS is consumed by schema/schema.sh, and running processes read the effective value back from the database.
Optional storage policies and cold-volume settings can move older parts to a colder ClickHouse volume while keeping table semantics unchanged.