AaronDB

"Simplicity is not about making things easy. It is about untangling complexity." - Rich Hickey

AaronDB is a BEAM-native temporal Datalog engine written in Gleam. Its strongest current shape is a fact-oriented database core built around a transactor actor, immutable-style state transitions, in-memory indexes, and a custom query engine.

This repository also contains experimental distributed, search, MCP, cognitive, and CMS layers. Those subsystems are not all at the same maturity level. See docs/feature_maturity.md and docs/project_boundaries.md before adopting non-core features.

Core Model

  1. Facts, not objects: data is represented as datoms.
  2. Actor-owned writes: a transactor process serializes state transitions.
  3. Query over values: reads execute against database state snapshots.
  4. Storage is pluggable: the engine is decoupled from persistence adapters.

What Is Solid Today

Maturity Snapshot

AreaStatusNotes
Core DB API (aarondb)StablePrimary strength of the repository
Query DSL and pull APIsStableBacked by passing tests
Temporal querying and diffStable/BetaUsable, but still tied to large core modules
Graph, vector, BM25, federationBetaImplemented, but less bounded than core
Sharding and distributed queriesBeta/ExperimentalWorks as scatter/gather; not a full distributed query fabric
Raft and HA claimsExperimentalLeader-election state machine exists; production consensus story is incomplete
MCP server and agent toolingExperimentalPartial tool coverage and explicit TODOs remain
GleamCMSExperimentalProduct layer mixed into the DB repo

Installation

Add aarondb to your gleam.toml:

[dependencies]
aarondb = "2.4.0"

Why 2.4.0 Is Better

AaronDB 2.4.0 completes the deeper solver and transactor redesign while keeping all tests green.

Basic Usage

Create an in-memory database:

import aarondb
let db = aarondb.new()

Transact facts:

import aarondb
import aarondb/fact.{EntityId, Str, Uid}
let assert Ok(_state) = aarondb.transact(db, [
#(Uid(EntityId(101)), "user/name", Str("Alice")),
#(Uid(EntityId(101)), "user/role", Str("Admin")),
])

Query with the DSL:

import aarondb
import aarondb/q
let query =
q.select(["name"])
|> q.where(q.v("e"), "user/role", q.s("Admin"))
|> q.where(q.v("e"), "user/name", q.v("name"))
|> q.to_clauses()
let results = aarondb.query(db, query)

Use temporal and pull APIs:

import aarondb
import aarondb/fact
let history = aarondb.history(db, fact.Uid(fact.EntityId(101)))
let entity = aarondb.pull(db, fact.Uid(fact.EntityId(101)), aarondb.pull_all())

Start a sharded cluster when you explicitly want the experimental distributed layer:

import aarondb/sharded
let assert Ok(cluster) = sharded.start_sharded("cluster", 4, None)

Documentation

Current Recommendation

Treat AaronDB first as a temporal Datalog engine with a strong in-memory core. Adopt peripheral layers only with explicit evaluation of their maturity and operational trade-offs.