Timeless

Embedded Time Series Database for Elixir

Hex.pmDocsLicense


“I found it ironic that the first thing you do to time series data is squash the timestamp. That’s how the name Timeless was born.” –Mark Cotner

TimelessMetrics is an embedded time-series database for Elixir with a Rust-native hot path, built-in HTTP ingest/query APIs, retention, rollups, alerting, scraping, charts, and Prometheus/VictoriaMetrics compatibility.

It runs:

Current Architecture

The default engine is the Rust engine.

Hot-path responsibilities live in the Rust NIF:

Elixir still owns the surrounding product surface:

If you need the detailed design, start with docs/architecture.md.

Documentation

Highlights

Quick Start

Add to mix.exs:

{:timeless_metrics, "~> 6.0"}

Add to your supervision tree:

children = [
  {TimelessMetrics, name: :metrics, data_dir: "/var/lib/metrics"},
  {TimelessMetrics.HTTP, store: :metrics, port: 8428}
]

Write and query:

TimelessMetrics.write(:metrics, "cpu_usage", %{"host" => "web-1"}, 73.2)

{:ok, points} =
  TimelessMetrics.query(:metrics, "cpu_usage", %{"host" => "web-1"},
    from: System.os_time(:second) - 3600,
    to: System.os_time(:second)
  )

Memory-only mode:

children = [
  {TimelessMetrics, name: :metrics, mode: :memory},
  {TimelessMetrics.HTTP, store: :metrics, port: 8428}
]

Elixir API

Writes:

TimelessMetrics.write(:metrics, "cpu_usage", %{"host" => "web-1"}, 73.2)

TimelessMetrics.write_batch(:metrics, [
  {"cpu_usage", %{"host" => "web-1"}, 73.2},
  {"mem_usage", %{"host" => "web-1"}, 4096.0}
])

Queries:

{:ok, points} =
  TimelessMetrics.query(:metrics, "cpu_usage", %{"host" => "web-1"},
    from: System.os_time(:second) - 3600
  )

{:ok, series} =
  TimelessMetrics.query_multi(:metrics, "cpu_usage", %{"host" => "web-1"},
    from: System.os_time(:second) - 3600
  )

{:ok, buckets} =
  TimelessMetrics.query_aggregate(:metrics, "cpu_usage", %{"host" => "web-1"},
    from: System.os_time(:second) - 3600,
    bucket: {60, :seconds},
    aggregate: :avg
  )

Discovery and operations:

TimelessMetrics.list_metrics(:metrics)
TimelessMetrics.list_series(:metrics, "cpu_usage")
TimelessMetrics.label_values(:metrics, "cpu_usage", "host")
TimelessMetrics.info(:metrics)
TimelessMetrics.flush(:metrics)
TimelessMetrics.backup(:metrics, "/tmp/metrics-backup")

HTTP API

Core endpoints:

Method Path Description
POST/api/v1/import VictoriaMetrics JSON-line ingest
POST/api/v1/import/prometheus Prometheus text ingest
POST/write Influx line protocol ingest
GET/api/v1/query Latest-value query
GET/api/v1/query_range Native range query
GET/api/v1/export Multi-series export
GET/prometheus/api/v1/query Prometheus instant query
GET/prometheus/api/v1/query_range Prometheus range query
GET/prometheus/api/v1/labels Prometheus label names
GET/prometheus/api/v1/series Prometheus series listing
GET/chart SVG chart
GET/health Lightweight health/status
GET/health/detailed More expensive store diagnostics

Example ingest:

curl -X POST http://localhost:8428/api/v1/import/prometheus \
  -H "Content-Type: text/plain" \
  --data-binary '
cpu_usage{host="web-1"} 73.2
cpu_usage{host="web-2"} 61.8
'

Example range query:

curl 'http://localhost:8428/api/v1/query_range?metric=cpu_usage&host=web-1&from=1700000000&to=1700003600&step=60'

Example Prometheus-compatible query:

curl 'http://localhost:8428/prometheus/api/v1/query_range?query=cpu_usage{host="web-1"}&start=1700000000&end=1700003600&step=60'

Benchmarks

The maintained benchmark set lives under bench/:

Notes