Skip to main content
Flux stores all data in a single DuckDB file located at FLUX_DUCKDB_PATH (default data/flux.duckdb). The schema is designed to be append-only — collections add rows and materialized “current” tables present the latest state for each resource or scope. Nothing is overwritten on collection; historical snapshots accumulate alongside current views.

Design principles

  • Snapshot, don’t overwrite. Every successful collection appends rows to a *_snapshots table. A corresponding *_current table (or view) presents the newest record per resource ID or scope, so resources absent from a later collection do not silently persist as current.
  • Four hot tables use CREATE OR REPLACE. The highest-read projections — resources_current, costs_current, commitment_costs_current, and policy_posture_current — are rebuilt as full replacement tables after each snapshot write and on startup. This provides O(1) lookup without recomputing arg_max window functions on every API read.
  • Exact-pinned DuckDB version. DuckDB is pinned to 1.4.5 in requirements.txt. A floating version range caused five corruption incidents in five days when different engine builds wrote and checkpointed the same on-disk file. Do not relax this pin.
  • All writes serialized through one worker. The singleton sync worker holds the DuckDB writer lock. Multiple concurrent writers are not safe — read-only API queries must acquire the cross-process read lease, and the web process returns 503 Retry-After rather than hanging when the writer holds the lock.

Configuration and sync


Inventory


Cost


Cost anomalies


Opportunities and valuation


Inventory drift


Telemetry and right-sizing


Intelligence


FinOps Toolkit


Virtual tags


Notes

Interactive API documentation covering all endpoints and response schemas is available at /docs (FastAPI Swagger UI).
The DuckDB file must not be opened by multiple writers simultaneously. All writes are serialized through the singleton sync worker. The web process acquires a cross-process read lease; API requests return 503 Retry-After rather than hanging when the writer holds the lock.