
knut
A pure-Rust columnar ↔ graph fabric — read/write Apache GraphAr, bulk-load FalkorDB, and serve Cypher over Arrow Flight SQL, with Bifröst streaming Iceberg tables into a live graph by CDC (Spark-Connect or Spark-free). One Arrow pipe from the lakehouse to a queryable graph.
⚡ part of the nordisk constellation
Mashup — one Arrow pipe: columnar lake → live graph
knut carries graph data the whole way from a columnar lake to a live, queryable graph in one Arrow pipe (no JVM required) — the rows marked NA are categories the rivals have no concept for:
| capability | knut | GraphAr (official) | Neo4j / GDS | Spark + GraphFrames |
|---|---|---|---|---|
| Pure-Rust GraphAr — 5 formats (Parquet/CSV/ORC/JSON/Arrow), local or object store | ✅ | ◐ (C++/Java/Py) | ✗ | ◐ |
| Cypher over Arrow Flight SQL server — ADBC / Power BI / DataFusion clients, Arrow out | ✅ | NA | ◐ | ✗ |
Iceberg → graph CDC fabric — snapshot-incremental + changelog (_change_type → MERGE / DETACH DELETE) | ✅ | NA | ✗ | ◐ |
Spark-free Iceberg ingestion (skade IcebergSource, no JVM) | ✅ | NA | ✗ | ✗ |
Bulk columnar RecordBatch → live graph DB (FalkorDB UNWIND/CREATE) | ✅ | ◐ | ✅ | ✅ |
| Mature graph-algorithm library + production graph engine | ◐ | ✗ | ✅ | ✅ |
Rows marked NA: the rival has no such category. The measured numbers are below.
Benchmarks
v0.1.3 · oden · 32 cores · 2026-07-23
| host | oden · 32 cores |
| version | 0.1.3 |
| measured | 2026-07-23 |
| arms | 29 |
| borrowed arms | 10 named nornir.* — measured here but owned by nornir |
| tests | 29/29 passed |
| publishable | yes |
| flagged implausible | 2 |
⚠ 2 arms carrying a number that is not credible as real work. Each is marked ⚠ or withheld wherever it appears below — never published as a measurement:
| arm | what is not credible |
|---|---|
bifrost_fabric | rows_per_s = 6.698e9/s derived from a 1.49e-5 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurement |
merge_property_groups | rows_per_s = 1.067e10/s derived from a 9.37e-6 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurement |
ℹ 10 arms in this run belong to another repo (10 × nornir.*). They are the harness's own suite, pulled in because the bench runner this repo pins predates the arm filter that would have excluded them — so they were measured here without being asked for. They describe nornir, not knut, and are shown separately below rather than mixed into this repo's numbers.
The Arrow pipe — knut's own arms
Storage formats round-tripped through the GraphAr writer/reader, the Bifröst CDC fabric, the FalkorDB bulk path, and the Thund streaming window operators.
v0.1.3 · oden · 32 cores · 2026-07-23
| workload | rows_per_s | read_rows_per_s | write_rows_per_s | incremental_rows_per_s | recompute_rows_per_s | checkpointed_rows_per_s | restore_resume_rows_per_s | speedup_x | telem_cores_busy_avg | telem_elapsed_ms |
|---|---|---|---|---|---|---|---|---|---|---|
| builder_dump | 1.42M | 1 | 71.43 | |||||||
| cypher_render | 3.21M | 1 | 38.22 | |||||||
| doput_dispatch | 0.85 | 1.60 | 4766 | |||||||
| falkor_parallel_dispatch | 29.75 | 1 | 801.77 | |||||||
| file_source_scan | 48.55M | 1 | 20.62 | |||||||
| format_arrow | 170.32M | 77.14M | 1 | 10.89 | ||||||
| format_csv | 8.18M | 5.44M | 2 | 42.19 | ||||||
| format_json | 1.08M | 8.44M | 2 | 113.17 | ||||||
| format_orc | 63.84M | 47.38M | 1 | 12.46 | ||||||
| format_parquet | 45.57M | 7.16M | 2 | 24.88 | ||||||
| graphar_vertex_load | 35.85M | 2 | 54.49 | |||||||
| ingest_lifecycle | 36.05M | 2 | 24.69 | |||||||
| thund_checkpoint | 14.11M | 2 | 157.51 | |||||||
| thund_incremental_agg | 6.13M | 1.80M | 1.50 | 1467 | ||||||
| thund_recovery | 33.59M | 1 | 129.08 | |||||||
| thund_watermark_drop | 2.22M | 3.81M | 1 | 36.46 | ||||||
| thund_window_close | 16.58M | 31.40M | 1 | 193.79 |
⚠ withheld from this table — not credible as real work:
bifrost_fabric—rows_per_s= 6.698e9/s derived from a 1.49e-5 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurementmerge_property_groups—rows_per_s= 1.067e10/s derived from a 9.37e-6 s interval — under the 1e-4 s timing floor, so the rate is arithmetic, not measurement
telem_cores_busy_avg is the average number of CPU cores busy while the arm ran —
a single-digit value on a 32-core host means the arm is serial by construction, not that
the box was idle. Blank cells are metrics that arm does not report.
Borrowed arms — nornir's own suite, measured here by accident
v0.1.3 · oden · 32 cores · 2026-07-23
| workload | elapsed_ms | rows_per_sec | queries_per_sec | symbols_per_sec | events_per_sec | speedup_vs_full | telem_cores_busy_avg |
|---|---|---|---|---|---|---|---|
| nornir.delta_rescan | 8.19 | 2.70 | 0 | ||||
| nornir.dep_graph_build | 24.07 | 365085 | 1 | ||||
| nornir.dep_graph_build_ext | 31.88 | 344637 | 1 | ||||
| nornir.funnel_append | 1284 | 49.84 | 1 | ||||
| nornir.funnel_append_batch | 1.23 | 52137 | 0 | ||||
| nornir.knowledge_query | 16.85 | 23742 | 1 | ||||
| nornir.knowledge_scan | 1.78 | 674582 | 0 | ||||
| nornir.plan_dag_assemble | 107.38 | 0 | |||||
| nornir.symbol_append | 4.59 | 239618 | 0 | ||||
| nornir.warehouse_query | 1.22 | 410561 | 0 |
These arms measure nornir, not knut. knut/xtask pins nornir = "0.5" from
crates.io, and that published runner predates the NORNIR_BENCH_ONLY arm filter — so the
filter was accepted and silently ignored, and nornir's suite ran alongside knut's. They
are kept in their own table so they can never be read as knut's numbers; the fix is a
newer runner, not an edit to this file.
SQL for Power BI lives next door (2026-09-09)
knut's Flight SQL server (graphar-flight) speaks Cypher — the graph. Power BI, the
Arrow Flight SQL ODBC driver and ADBC speak SQL, and that dialect is
skade-flight in the skade
repo: DataFusion over the Iceberg warehouse, streamed Arrow, ODBC escapes translated, 129 Power Query
statement shapes green. Two dialects, two services, one wire; korp mounts both. The knut bridge —
graph tables as DataFusion table providers in that same session — is the next step, not done.
Read the real docs
- 📖 The complete manual —
docs/manual.pdf— every subsystem chapter (graphar, graphar-falkordb, graphar-flight, Bifröst, pipelines) plus the test & bench matrix. - 📄 Full overview —
.nornir/README-full.md— the detailed pitch, architecture, quickstart, per-crate reference, and the full test matrix. - 📝
docs/book.md— the manual, as Markdown. Search it withnornir docs search knut "<query>".