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:

MethodPathDescription
POST/api/v1/importVictoriaMetrics JSON-line ingest
POST/api/v1/import/prometheusPrometheus text ingest
POST/writeInflux line protocol ingest
GET/api/v1/queryLatest-value query
GET/api/v1/query_rangeNative range query
GET/api/v1/exportMulti-series export
GET/prometheus/api/v1/queryPrometheus instant query
GET/prometheus/api/v1/query_rangePrometheus range query
GET/prometheus/api/v1/labelsPrometheus label names
GET/prometheus/api/v1/seriesPrometheus series listing
GET/chartSVG chart
GET/healthLightweight health/status
GET/health/detailedMore 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