logo
Kurashizu Blogwhere ideas flow
  • Home
  • News
  • Blog
  • About
  • Home
  • News
  • Blog
  • About

© 2026 Kurashizu. All rights reserved.

Admin·New Post·Service Status
Powered by Cloudflare·30.10.26
← Back to news

Show HN: Minigraf – An embedded, bi-temporal graph database in Rust

Original article
github.com|24 points|16 comments|by adityamukho|Oct 5, 2026

Minigraf: A Rust-Powered Embedded Bi-Temporal Graph Database

crates.io docs.rs Build Status Clippy Status Coverage License: MIT OR Apache-2.0 Rust Edition MSRV

Minigraf is designed to be the "SQLite of bi-temporal graph databases." It provides a lightweight, self-contained memory system for graph data, specifically tailored for mobile applications, AI agents, and browser-based environments. It combines the power of Datalog queries with the ability to "time travel" through data history.

Quick Links: Try it in your browser | Explore the Time Travel Visualizer


🎯 The Vision

Minigraf aims to provide a single-file embedded solution that eliminates complex setup. Its core capabilities include:

  • Datalog Querying: Support for recursive rules and intuitive graph traversal.
  • Bi-Temporal History: Ability to query based on both transaction time and valid time.
  • Advanced Window Functions: Support for :over (partition-by ... :order-by ...) with functions like sum, count, min, max, avg, rank, and row-number.
  • Prepared Statements: Optimize performance by parsing and planning once using $slot tokens, then executing repeatedly.
  • Universal Embedding: Works across Native, WASM, IoT, and mobile via a single .graph file.
  • Zero-Config: Get started instantly with Minigraf::open("data.graph").

Understanding Bi-Temporality

In Minigraf, a fact is not just a triple, but a temporal entity. Mathematically, a fact can be represented as: Fact=(Entity,Attribute,Value,Tvalid,Ttransaction)\text{Fact} = (Entity, Attribute, Value, T_{valid}, T_{transaction})Fact=(Entity,Attribute,Value,Tvalid​,Ttransaction​)


🧠 Why Datalog?

The developers argue that Datalog is fundamentally superior to SQL-like languages for graph workloads:

  1. Native Recursion: Multi-hop traversals are a core feature, not a complex add-on.
  2. Reliability: A smaller specification leads to faster production cycles and fewer bugs.
  3. Temporal Synergy: Time is treated simply as another dimension within the relations.
  4. Industry Proven: Built on 40+ years of research and used in systems like XTDB and Datomic.
  5. Graph-Centric: Facts are stored as Entity-Attribute-Value (EAV), which are essentially edges.
  6. AI-Ready: Because the grammar is uniform (e.g., [?e :attr ?v]) and lacks complex JOIN variants, LLMs can generate accurate queries with very few examples.

🛠️ Installation & Setup

Add the following to your Cargo.toml:

[dependencies]
minigraf = "2.0.2"

Alternatively, use the CLI: cargo add minigraf

Requirement: You must be using Rust 1.89 or a newer version.

⚠️ Known Issues

Everything is perfect →\rightarrow→ There are some bugs in the current release. The most critical issue in v2.x is that writing or retracting two values of the same attribute for one entity within a single transaction may result in only one value being read back (Issue #371).

Workaround: Perform a separate call for each value when dealing with multi-valued attributes. Note: v2.x will receive security and integrity patches for 12 months after v3.0.0 is released.


🚀 Quick Start Guide

use minigraf::{Minigraf, OpenOptions, BindValue};

// Initialize a file-backed database
let db = OpenOptions::new().open("my_data.graph")?;

// 1. Insert data (Transact)
db.execute(r#"(transact [
    [:alice :person/name "Alice"] 
    [:alice :person/age 30] 
    [:alice :friend :bob] 
    [:bob :person/name "Bob"]
])"#)?;

// 2. Basic Query
db.execute(r#"(query [:find ?friend-name :where [:alice :friend ?friend] [?friend :person/name ?friend-name]])"#)?;

// 3. Temporal Query (As of transaction 1)
db.execute("(query [:find ?age :as-of 1 :where [:alice :person/age ?age]])")?;

// 4. Define Recursive Rules
db.execute(r#"(rule [(reachable ?a ?b) [?a :friend ?b]]) (rule [(reachable ?a ?b) [?a :friend ?m] (reachable ?m ?b)])"#)?;

// 5. Prepared Statements for high performance
let pq = db.prepare("(query [:find ?name :as-of $tx :where [$entity :person/name ?name]])")?;
pq.execute([
    ("tx", BindValue::TxCount(1)), 
    ("entity", BindValue::Entity(alice_id))
])?;

Running the project:

  • cargo run →\rightarrow→ Launches the interactive Datalog REPL.
  • cargo test →\rightarrow→ Executes the 1,212 test suite.
  • cargo run demos/demo_recursive.txt →\rightarrow→ Runs the recursion demo.

📊 Comparison & Compatibility

Feature Matrix

FeatureMinigrafXTDBCozoNeo4jSQLite
Query LanguageDatalogDatalogDatalogCypherSQL
Single File✅ Yes❌ No❌ No❌ No✅ Yes
Bi-temporal✅ Yes✅ Yes⚠️ Limited❌ No❌ No
Embedded✅ Yes✅ Yes✅ Yes❌ No✅ Yes
Graph Native✅ Yes✅ Yes✅ Yes✅ Yes❌ No
Rust✅ Yes❌ NoClojure✅ Yes❌ Java
WASM Ready✅ Yes❌ No⚠️ Limited❌ No✅ Yes

Platform Support

PlatformTierPackageInstall Command
Rust (Native)1minigraf (crates.io)cargo add minigraf
Python1minigraf (PyPI)pip install minigraf
Browser WASM2*@minigraf/browser (npm)npm install @minigraf/browser
WASI2*@minigraf/wasi (npm)npm install @minigraf/wasi
Node.js2*minigraf (npm)npm install minigraf
Java/JVM2*minigraf-jvm (Maven)See Wiki
Android2*minigraf-android (.aar)See Wiki

*Experimental


🧪 Demos & Exploration

  • Temporal Reasoning AI: Check out github.com/adityamukho/temporal_reasoning to see an AI agent using Minigraf to store, audit, and correct its beliefs.
  • Visualizer: Use the browser-based tool to scrub through transaction and valid time to see how the graph evolves (e.g., correcting a misrecorded salary).