MCPcopy Index your code
hub / github.com/aymanhs/nanotdb

github.com/aymanhs/nanotdb @v1.4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.4.0 ↗ · + Follow
1,213 symbols 4,808 edges 96 files 116 documented · 10%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

NanoTDB

NanoTDB mascot

Single-binary observability, time-series storage, and built-in dashboards for Raspberry Pi, edge devices, appliances, and local metrics.

Ingest metrics, query history, explore series, edit dashboards in the browser, and inspect data offline with nanocli without assembling a separate TSDB, dashboard service, or support stack.

Designed for the cases where a bigger observability stack is heavier than the problem: one machine, local files, clear operational behavior, and a UI that is ready as soon as the binary starts.

One binary. Local files. Built-in dashboard and editor. Offline CLI.

Get Started Fast

  1. Start nanotdb against a local data directory.
  2. Send line protocol directly or collect host metrics with drip.
  3. Open the built-in dashboard or Explore to see live metrics immediately.
  4. Use the in-browser editor or nanocli when you want to shape dashboards or inspect data offline.

Typical Workflow

Run drip on a Raspberry Pi or small Linux box to collect host metrics, store them locally in NanoTDB, inspect them live in the built-in dashboard or Explore, and use nanocli when you need offline inspection, export, recovery, or rollup operations.

Sample Footprint

Actual live Raspberry Pi data:

  • 84 metrics collected every 10 seconds
  • About 700,000 samples per day
Day Metrics Points Metric file size Coverage
2026-05-22 83 693,091 757 KB 24h
2026-05-23 83 717,036 935 KB 24h
NanoTDB dashboard showing CPU and memory widgets
Mobile-friendly dashboard showing a compact live operational view.
NanoTDB wide desktop dashboard layout
Wide desktop dashboard layout for larger operational views.
NanoTDB Explore view with metric picker and live chart
Explore for ad hoc metric lookup and charting.
NanoTDB dashboard editor
In-browser dashboard editor for groups, widgets, series, preview, validation, and save.

Product Tour

  • Dashboard: mobile-friendly live CPU, memory, disk, and sensor-style widgets from one local NanoTDB instance.
  • Dashboard Wide: a wider desktop dashboard layout for broader operational views on larger screens.
  • Explore: ad hoc metric selection with a live chart and last-value cards for long metric names and quick drill-down.
  • Dashboard Editor: in-browser editing for groups, widgets, series, preview, validation, and save.

Everything In One Binary

  • Metric ingest API for local applications, devices, and collectors.
  • Built-in dashboard for live operational views on both mobile-width and desktop-width layouts.
  • Built-in dashboard editor for in-browser dashboard authoring.
  • Explore view for ad hoc metric lookup and charting.
  • Engine inspector for operational state, files, runtime, and settings.
  • Offline CLI tools for inspect, export, import, recover, and rollup workflows.
  • Rollups and query-optimized metric files without adding separate services.

When Simpler Wins

Question NanoTDB Bigger stack
Single Raspberry Pi or edge box? One binary, local files, built-in dashboard Usually multiple services and more moving parts
Need local observability first? Storage, UI, CLI, and rollups are already together Often starts with separate TSDB + dashboard + supporting services
Want to inspect everything on disk? WAL, manifests, catalog, and data files stay understandable More layers and components between writes and storage
Need huge fleet-scale cardinality? Not the target Usually the better fit

Why Teams Pick It

  • One deployable binary: ingest, query, dashboard, Explore, editor, and local operations ship together.
  • Fast path to visibility: start writing metrics and open a usable dashboard immediately instead of assembling a separate stack first.
  • Built for small systems: a strong fit for Raspberry Pi, edge nodes, appliances, and local application metrics.
  • Files you can inspect: WAL, catalog, manifests, raw partitions, and metric files stay understandable on disk.
  • Offline by default: nanocli lets you inspect, export, recover, and compare data without a running server.
  • Read-optimized when needed: optional metric files and built-in rollups improve read paths without adding extra services.
  • Operationally boring: no runtime dependency chain, no separate dashboard service, and retention maps cleanly to file deletion.

Best For

Good fit Use something larger
Single-binary observability on one machine Distributed or horizontally scaled deployments
Raspberry Pi, edge nodes, appliances, and local app metrics Large fleets and high-cardinality multi-tenant workloads
Hundreds of metrics you want to keep local and inspect directly Broader ecosystems where many external integrations matter more than simplicity
Built-in dashboard plus offline CLI workflow Systems that need looser ordering guarantees or broader platform features

NanoTDB fits best when you want:

  • Single-binary observability on one machine.
  • Local metrics storage with a built-in dashboard.
  • Something you can understand from the filesystem.
  • A TSDB for hundreds of metrics, not huge multi-tenant cardinality.
  • A small self-hosted stack for sensors, host telemetry, appliances, or embedded apps.

Not Built For

NanoTDB is not trying to be:

  • A distributed or horizontally scaled TSDB.
  • A high-cardinality metrics backend for large fleets.
  • A system that accepts arbitrary out-of-order writes.
  • A system that hides its durability tradeoffs behind marketing language.

Common Uses

Raspberry Pi and edge host telemetry

NanoTDB is a strong fit for small Linux systems where you want to keep metrics local, survive restart, and avoid wearing out SD storage with unnecessarily heavy write patterns. Pair it with drip when you want CPU, memory, disk, IO, network, load, one-wire, or SD write probe metrics on one box, then view them through the built-in dashboard without standing up a second service.

Local app metrics without a bigger stack

If you have one appliance, one embedded app, or one self-hosted node, NanoTDB gives you metric writes, queries, rollups, dashboarding, and offline inspection without standing up a larger metrics platform just to answer simple history questions.

Sensor retention you can inspect directly

If your data is fundamentally numeric time-series data, NanoTDB is often easier to live with than plain logs. You keep a queryable history, can inspect the WAL or .dat files directly with nanocli, and can delete old partitions as a simple retention policy.

Long-horizon summaries on small disks

When you want recent raw detail plus longer-term summaries, NanoTDB's built-in rollups let you keep local aggregates without building a separate compaction or downsampling pipeline.


🚀 Quick Start

Start here:

  • Hello World for the fastest copy/paste path.
  • Getting Started for installation, examples, and a longer guided tour.
  • Dashboard for the built-in UI, dashboard.json, and dashboard/editor workflow.
  • Metric Files for query-optimized metric storage, config, inspection, and standalone benchmarking.
  • Run As A Service for a brief systemd setup path.
  • Glossary for the canonical meaning of database, metric, sample, WAL, and related terms.
  • Contributing for the branch model and release workflow.

60-Second Hello World

Terminal 1:

mkdir -p ~/nanotdb-data
./nanotdb --init --config ~/nanotdb-data/engine.toml
./nanotdb --config ~/nanotdb-data/engine.toml

Terminal 2:

curl -X POST "http://localhost:8428/api/v1/import" \
  -d $'demo/room.temp 21.5\ndemo/room.humidity 48'

curl "http://localhost:8428/api/v1/query?query=demo/room.temp"

./nanocli inspect wal --root ~/nanotdb-data --db demo --verbose

That flow is the point of NanoTDB: start one binary, write a few metrics, query them back, inspect the local files, and serve a local dashboard without standing up anything else.

For the built-in browser UI and dashboard customization, see docs/DASHBOARD.md.

Prefer ready-to-use binaries? Download the latest release assets from GitHub Releases:

  • Old Raspberry Pi (Pi 0/1): nanotdb-linux-armv6-rpi0-rpi1 and nanocli-linux-armv6-rpi0-rpi1
  • Newer 32-bit Raspberry Pi OS (Pi 2/3/4): nanotdb-linux-armv7-rpi3-rpi4 and nanocli-linux-armv7-rpi3-rpi4
  • 64-bit Raspberry Pi OS: nanotdb-linux-arm64 and nanocli-linux-arm64

Release/change history:

For technical deep-dives, continue below.


Core Concepts

What is a database?

A database in NanoTDB is an isolated local namespace such as prod, sensors, or weather.

Each database has its own:

  • metrics
  • WAL file
  • catalog
  • manifest
  • partitioned .dat files

That makes it easy to reason about retention, inspection, backup, and failure isolation one database at a time.

What is a metric?

A metric is one numeric time-ordered stream inside a database.

Examples:

  • room.temp
  • room.humidity
  • cpu.usage_active
  • disk.sd_write_probe_ms

Each metric keeps one numeric type for its lifetime: int32 or float32.

What does a sample look like?

NanoTDB writes and reads line protocol in this shape:

DB/metric.name value [timestamp]

Examples:

prod/room.temp 21.5 1715000000000000000
sensors/pressure.hpa 1013
weather/outdoor.humidity 48
  • DB is the database name.
  • metric.name is the metric identifier.
  • value is an integer or float.
  • timestamp is optional; if omitted, NanoTDB uses the current time.

For a deeper storage and query walkthrough, see docs/ARCHITECTURE.md.

What is the WAL?

WAL means write-ahead log.

In NanoTDB, each database has a local <db>.wal file that protects the newest samples before they are flushed into durable .dat pages.

That matters for both crashes and normal shutdown:

  • On clean shutdown, NanoTDB flushes open pages before exit so recent samples move into durable data files.
  • On restart after a crash or power loss, NanoTDB replays the WAL so unflushed samples can be recovered into the in-memory open page state.
  • Once a page is flushed and no open page still depends on that WAL content, the WAL can be reset.

This is one of NanoTDB's strongest operational properties for edge systems: the latest data is not only local, it is recoverable after restart without needing an external service.

How WAL and recovery can be tuned

The main WAL and durability knobs are in engine.toml and per-database manifests:

  • wal.max_segment_size: how large the WAL is allowed to grow before reset after flush.
  • wal.fsync_policy: segment for better throughput, always for stronger per-append durability.
  • durability.profile: strict, balanced, or throughput for page/catalog fsync behavior.
  • manifest_defaults.wal.enabled: enable or disable WAL for newly created databases.
  • manifest_defaults.wal.skip_before: skip WAL for older backfill samples.
  • manifest_defaults.page.max_records, max_bytes, and max_age: control how quickly in-memory pages roll over and flush, which affects how long data remains WAL-backed before landing in .dat files.

If you want the strongest local recovery posture, the conservative end of the range is:

  • wal.fsync_policy = "always"
  • durability.profile = "strict"

If you want less write overhead and can tolerate more crash risk, move toward segment and balanced or throughput.

Why the data files matter

NanoTDB's durable .dat files are small, append-only, and friendly to simple retention and backup workflows.

That matters operationally, especially on SD-backed systems:

  • small files are easier to inspect and copy
  • retention is just removing old partition files
  • append-only writes are easier on flash media than rewrite-heavy designs
  • compressed page files keep local history practical on small disks

As one real Pi test point, a 69-metric workload sampled every 10 seconds produced about 0.7 MB for a full day in one .dat file, which worked out to under 2 bytes per metric point on disk after compression. Treat that as a real-world example, not a universal promise, but it shows why NanoTDB can be a very SD-friendly fit for local telemetry.

Why not plain logs?

Plain logs are often enough until you want to ask metric-shaped questions like:

  • what was the last temperature?
  • show me the last 24 hours of humidity
  • downsample this series for a dashboard
  • inspect the local data without shipping it anywhere else

You can force numeric history into logs, but querying, retention, aggregation, and inspection stay awkward. NanoTDB keeps the operational simplicity of local files while giving you metric-native writes, queries, rollups, and offline inspection.

Why not a heavier TSDB?

Sometimes a larger metrics stack is the right answer. NanoTDB is for the cases where it is not.

Choose NanoTDB when you want:

  • one local node instead of a broader platform
  • plain files you can inspect and back up directly
  • hundreds of metrics

Extension points exported contracts — how you extend this code

Aggregator (Interface)
Aggregator computes one aggregate value for a time window. points are source metric values collected for that window. [7 …
internal/engine/aggregates.go
Collector (Interface)
Collector defines the interface for metric collectors. [9 implementers]
cmd/drip/collectors/collector.go
SampleCallback (FuncType)
SampleCallback is invoked for each sample in a range query.
internal/engine/engine.go
BlockCompressionCodec (Interface)
(no doc) [2 implementers]
internal/engine/compression.go
AggregateBucketCallback (FuncType)
(no doc)
internal/engine/query_aggregates.go
DataFrameCallback (FuncType)
(no doc)
internal/engine/datstats.go

Core symbols most depended-on inside this repo

Close
called by 228
internal/engine/wal.go
OpenEngine
called by 140
internal/engine/engine.go
AddLine
called by 100
internal/engine/engine.go
AddSample
called by 93
internal/engine/pages.go
number
called by 65
internal/web/static/engine_assets/engine_app.js
getOrCreateDB
called by 62
internal/engine/engine.go
writeVMError
called by 62
cmd/nanotdb/main.go
set
called by 53
internal/engine/enginestats.go

Shape

Function 799
Struct 202
Method 198
FuncType 4
TypeAlias 4
Class 3
Interface 3

Languages

Go83%
TypeScript15%
Python2%

Modules by API surface

internal/engine/engine.go113 symbols
internal/engine/metricfile_v2.go79 symbols
internal/web/static/dashboard_assets/editor_app.js57 symbols
internal/engine/engine_test.go46 symbols
internal/web/static/dashboard_assets/dashboard_app.js40 symbols
internal/engine/metricfile_v1.go39 symbols
cmd/nanotdb/engine_ui.go39 symbols
cmd/nanotdb/main.go35 symbols
internal/engine/rollup.go32 symbols
internal/engine/aggregates.go31 symbols
cmd/nanocli/csv2nlp.go29 symbols
internal/web/static/engine_assets/engine_app.js28 symbols

For agents

$ claude mcp add nanotdb \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact