persistent · immutable · queryable

Branch databases, not just code

Datahike brings git-like semantics to your data: hold a snapshot, pass it across threads or machines, query any point in time—without copying or locking. Built on structural sharing and copy-on-write, it's the foundation for auditable, reproducible systems.

Vectory — fast vector search on immutable storage

A high-performance HNSW (Hierarchical Navigable Small World) vector index designed for Datahike's persistent model. Same semantic-search speed you expect—without mutation, without locks, with full audit history.

Memory model

Traditional databases expose connections; Datahike exposes values. A database snapshot is an immutable value—hold it in a variable, pass it to a function, serialize it, or compare two snapshots structurally.

Git-like operations

  • Hold — capture a point-in-time reference, query it later
  • Branch — create divergent histories without copying data
  • Merge — reconcile branches with custom conflict resolution

Why it matters

  • Coordination-free reads — no locks, no connection pool bottlenecks
  • Reproducible queries — same snapshot always yields same results
  • Full audit trail — query any past state, not just "last 7 days"

Structural sharing keeps memory efficient—branches share unchanged structure.

Datahike

An open-source, immutable Datalog database written in Clojure with full Java and JavaScript APIs. Datomic-compatible semantics, pluggable storage, and a query engine built on hitchhiker-tree indices for efficient range scans and joins.

Show me

Examples in Java. Native Clojure and JavaScript APIs also available.

Connect

import datahike.java.Datahike;
import static datahike.java.Util.*;

var cfg = map(kwd(":store"), map(
    kwd(":backend"), kwd(":file"),
    kwd(":path"), "/tmp/db"));
Datahike.createDatabase(cfg);
var conn = Datahike.connect(cfg);

Transact

Datahike.transact(conn, list(
    map(kwd(":user/name"), "Ada",
        kwd(":user/email"), "ada@example.com")));

Query

// Datalog query (EDN syntax)
var results = Datahike.q(
    "[:find ?e ?name :where [?e :user/name ?name]]",
    Datahike.deref(conn));
// => #{[1 "Ada"]}

Time-travel

// Query a past snapshot
var oldDb = Datahike.asOf(
    Datahike.deref(conn),
    Date.from(Instant.parse("2024-01-01T00:00:00Z")));
var history = Datahike.q(
    "[:find ?name :where [_ :user/name ?name]]",
    oldDb);

Full Datalog — joins, aggregates, pull expressions, rules.

JavaScript / Node.js (work in progress)

const d = require('datahike');

const config = { store: { backend: ':mem', id: 'example' } };
await d.createDatabase(config);
const conn = await d.connect(config);

await d.transact(conn, {
  'tx-data': [{ ':name': 'Alice', ':age': 30 }]
});

const results = await d.q(
  '[:find ?name ?age :where [?e :name ?name] [?e :age ?age]]',
  d.db(conn)
);
// => [['Alice', 30]]

TypeScript definitions included. Same Datalog queries, Promise-based API.

Notes

Occasional writing on databases, immutability, and semantic search.

Try it

A browser-based REPL is in progress. In the meantime, try Datahike locally:

<!-- Maven -->
<dependency>
    <groupId>io.replikativ</groupId>
    <artifactId>datahike</artifactId>
    <version>0.6.1559</version>
</dependency>

Works on JVM, Node.js, and browser (ClojureScript).

Support & consulting

Need help integrating Datahike or Vectory into production? We offer training, architecture review, and custom development.