NanoTDB
A small, embedded time-series database designed for resource-constrained hosts (Raspberry Pi, edge nodes, IoT gateways). No external dependencies at runtime. All data lives in plain files under a single root directory.
Architecture overview
Engine ├── "prod" Database → WAL (prod.wal) + Catalog (catalog.json) + partitioned .dat files ├── "sensors" Database → WAL + Catalog + partitioned .dat files └── "internal" → engine self-metrics (same layout, never exposed to users)
The Engine is the single entry point. It owns a collection of named databases and routes ingested samples to the right one based on the line-protocol prefix.
Each Database has three storage layers:
Layer File Purpose WAL <db>.wal Crash-safety: records every sample before it enters the page Catalog catalog.json Maps metric names ↔ compact MetricIDs + value types Data files data-<partition>.dat Immutable compressed pages flushed from memory
Data flow
Ingest ( AddLine )
AddLine("prod/room.temp 21.5 1715000000000000000") │ ├─ parse line protocol → dbName="prod" metric="room.temp" ts=… value=21.5 ├─ getOrCreateDB → open or reuse prod Database ├─ WAL append → write compact record to prod.wal (crash-safe) ├─ addToOpenDay → append to in-memory Page for today's bucket └─ if page full → compress + write page frame to data-<partition>.dat reset WAL (replay no longer needed)
... continue reading