Embedded · Rust core · Apache 2.0

A time-series database that lives inside your process.

Fieldnote is a single dependency and a single file on disk. No server to run, no port to open, no cluster to reason about. It handles a few billion points on one machine and gets out of the way.

cargo add fieldnote

1.4 M

Points ingested per second

11 MB

Compiled, no dependencies

0

Processes to supervise

main.rs

use fieldnote::{Db, Point, Window};

// one file, no server, no config
let db = Db::open("sensors.fn")?;

db.write("greenhouse.temp", Point {
    at:    now(),
    value: 21.4,
    tags:  &[("bed", "north")],
})?;

// downsample four million rows
let hourly = db
    .series("greenhouse.temp")
    .between(week_ago(), now())
    .window(Window::Hours(1))
    .mean()?;

assert_eq!(hourly.len(), 168);

Three reasons it is a library and not a server.

Most time-series workloads are a single machine writing to a single disk. Fieldnote is built for that case and declines the rest.

Nothing to operate

No daemon, no config file, no health check, no upgrade window. The database is a struct in your binary, and it goes away when your process does.

Queries are functions

There is no query language to learn or to escape. Windows, aggregates and joins are ordinary methods, checked by the compiler like the rest of your code.

One file, portable

The on-disk format is documented in nine pages and stable since v2.0. Copy the file to another machine and it opens, on any platform Rust targets.

Reference

The whole public surface is thirty-one functions. This is most of them.

Db::open(path)

Open or create a database file

v1.0
Db::write(series, point)

Append one point, fsync optional

v1.0
Db::write_batch(series, &[point])

Append many, one syscall

v1.4
Db::series(name)

Begin a query on one series

v1.0
Query::between(from, to)

Bound the range, inclusive

v1.0
Query::window(unit)

Bucket into fixed intervals

v1.2
Query::mean() / max() / p99()

Reduce each bucket

v1.2
Query::tagged(key, value)

Filter by tag, index-backed

v2.0
Db::compact()

Rewrite and reclaim, online

v2.1
Db::snapshot(path)

Consistent copy without stopping writes

v2.4

Benchmarks, with the losses included.

Single machine, 8 cores, NVMe. Fieldnote loses on distributed fan-out because it does not do distributed fan-out.

WorkloadFieldnoteServer AServer B
Ingest, 1 series1.42 M/s0.61 M/s0.88 M/s
Ingest, 10k series0.94 M/s0.55 M/s0.71 M/s
Range scan, 30 days42 ms118 ms96 ms
Hourly downsample, 1 yr210 ms640 ms480 ms
Fan-out across 6 nodesnot supported1.9 s1.1 s
Cold start3 ms2.4 s1.8 s

Reproduce with cargo bench --bench compare. The harness and the competitor configs are in the repository; corrections are welcome as issues.

If you need a cluster, use a cluster.

Fieldnote is for the very common case where you do not. It is Apache 2.0, has no corporate owner, and the maintainers answer issues on weekdays.

Read the reference