What did the application know then?
Query an earlier point in time or inspect the complete history without maintaining a separate audit representation.
Explore queryable history
GitHub
VevDB is a native embedded database with immutable database values, Datalog, queryable history, and hypothetical transactions.
current = database(connection)
// "current" is an immutable database value
proposed = with(current,
set task[42].status = approved
)
// "proposed" is another database value
query(current, task[42].status) // pending
query(proposed, task[42].status) // approved
// No write was performed.
// The connection still holds the original value.
query(
database(connection),
task[42].status
) // pending
You do not need to arrive wanting a new database paradigm. Start with history, a proposed change, or connected application data.
Query an earlier point in time or inspect the complete history without maintaining a separate audit representation.
Explore queryable historyApply facts to an immutable database value, run queries or rules against the result, then keep it or discard it.
Explore hypothetical stateQuery graph-like relationships with Datalog instead of accumulating one-off joins and traversal code.
Explore Datalog queriesCapture an immutable database value and pass it into ordinary application functions. It is a stable snapshot, not a copy of all its data. Each function sees one stable world, can query it freely, and returns data instead of performing I/O.
This makes a functional core and imperative shell a natural fit:
decision logic receives db and a command; the shell owns
the connection, transactions, and external effects.
// Pure function: values in, values out
function decide(db, command):
allowed = query(db, rules_for(command))
if not allowed:
return rejection
facts = facts_for(command)
next_db = with(db, facts)
effects = query(next_db, effects_to_emit)
return { facts, effects }
// Imperative shell: I/O stays at the boundary
db = database(connection)
result = decide(db, command)
transact(connection, result.facts)
send(result.effects)
Pass decide a current value, an earlier value, or a proposed value. The function itself does not change.
Embed VevDB in an application and open an in-memory or durable store. The database engine runs inside the application as a small native library.
VevDB fits applications where SQLite would be the natural choice for simple deployment, but the domain benefits from immutable database values, Datalog, queryable history, or hypothetical transactions. Use it from native software or through the Clojure and Java packages.
VevDB focuses on the embedded data model instead of growing into a database platform. That makes it a natural fit for self-contained desktop tools, developer products, on-premises applications, and resource-constrained single-node services.
3–4 MB native SDK downloads in v0.4.0
Embed VevDB directly through its stable C ABI or use a language package built on top. The database, query engine, and durable storage all run inside the application process.
vev_conn_t conn = vev_conn_open_memory();
const char *report = vev_transact_edn(
conn,
"[{:db/id 1 :project/name \"Atlas\"}]"
);
vev_string_free(report);
vev_value_handle_t rows = vev_query_value(
conn,
"[:find ?name :where "
"[?e :project/name ?name]]"
);
puts(vev_value_handle_edn(rows)); // #{["Atlas"]}
vev_value_handle_free(rows);
vev_conn_close(conn);
VevDB also exposes the SQLite bundled into its native library, so an application can use both storage models without shipping another database dependency.
VevDB
Relationships, history, audit, business state, and data you want to query as immutable values.
Bundled SQLite API
Caches, sessions, jobs, email queues, search indexes, and other data that should be updated in place.
The two stores use separate database files. Transactions do not span both stores. Read the SQLite API guide.
Query relationships with joins, rules, predicates, aggregates, negation, disjunction, and pull expressions.
Hold and query stable database values while the connection continues accepting transactions.
Use historical views, as-of, since, and transaction-range reads.
Open transient in-memory databases or durable stores backed internally by bundled SQLite.
Use entities, lookup refs, pull, reverse references, range scans, and EAVT/AEVT/AVET/VAET indexes.
Use the stable C ABI directly or through a language package. The query engine and storage run in-process.
| Language | Status | Package or documentation |
|---|---|---|
| C | Built in | C ABI guide |
| Kvist | Built in | Kvist API |
| Clojure | Available | vevdb/vev-clj |
| Java | Available | vevdb/vev-java |
| Odin | Available | vevdb/vev-odin |
Start with the native SDK, the command-line interface, or a language package. VevDB is open source under EPL-2.0.
$ vevdb transact example.db transactions.edn
$ vevdb query example.db query.edn
We would love to hear about projects where VevDB might be useful, whether you are actively evaluating it or simply exploring the model. If production is the goal, we are especially interested in what you would need before you could adopt it.
Email is private. The GitHub alternative opens a pre-filled public issue.