Query what is, what was, and what could be.

vevdb.com · 2026-09-27 · by Long Nguyen ·generic
VevDB is a small native embedded database with immutable database values, Datalog, queryable history, and hypothetical transactions.

Query what is, what was, and what could be.

Query what is, what was, and what could be.

VevDB is a native embedded database with immutable database values, Datalog, queryable history, and hypothetical transactions.

Get started Download

  • Runs in-process
  • In-memory or durable
  • macOS, Linux, Windows
  • Pseudocode Database as a value

    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

    Start with the problem you have.

    You do not need to arrive wanting a new database paradigm. Start with history, a proposed change, or connected application data.

    History / audit

    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 What-if / planning

    What would be true after this change?

    Apply facts to an immutable database value, run queries or rules against the result, then keep it or discard it.

    Explore hypothetical state Connected state

    How is this application data related?

    Query graph-like relationships with Datalog instead of accumulating one-off joins and traversal code.

    Explore Datalog queries

    Pass the whole database to a function.

    Capture 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.

    Read the article

  • The same function can receive current, historical, or hypothetical state.
  • Tests pass in a database value without giving the core a live connection.
  • Long-running work can keep a stable snapshot while new transactions arrive.
  • Pseudocode Functional core / imperative shell

    // 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.

    A component you can ship with the application

    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 it through a stable C ABI.

    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.

    Read the C ABI guide

    C A complete in-process round trip

    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);

    Not everything belongs in history.

    VevDB also exposes the SQLite bundled into its native library, so an application can use both storage models without shipping another database dependency.

    VevDB

    Durable domain facts

    Relationships, history, audit, business state, and data you want to query as immutable values.

  • Datalog and pull
  • Queryable history
  • Hypothetical transactions
  • Bundled SQLite API

    Operational and derived state

    Caches, sessions, jobs, email queues, search indexes, and other data that should be updated in place.

  • Ordinary SQL
  • FTS5 included
  • No additional native library

The two stores use separate database files. Transactions do not span both stores. Read the SQLite API guide.

The pieces for rich application state

Datalog queries

Query relationships with joins, rules, predicates, aggregates, negation, disjunction, and pull expressions.

Immutable snapshots

Hold and query stable database values while the connection continues accepting transactions.

History and time

Use historical views, `as-of`, `since`, and transaction-range reads.

Memory or disk

Open transient in-memory databases or durable stores backed internally by bundled SQLite.

Entity and index access

Use entities, lookup refs, pull, reverse references, range scans, and EAVT/AEVT/AVET/VAET indexes.

Native embedding

Use the stable C ABI directly or through a language package. The query engine and storage run in-process.

APIs

| 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 |

Open a store. Transact facts. Query a value.

Start with the native SDK, the command-line interface, or a language package. VevDB is open source under EPL-2.0.

Read the getting started guide View source

$ vevdb transact example.db transactions.edn
$ vevdb query example.db query.edn

Tell us what you are building.

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 hello@vevdb.com Open a public GitHub issue

Email is private. The GitHub alternative opens a pre-filled public issue.

Go deeper

Getting started Open a database, transact data, and run a query. Data model Datoms, entities, attributes, transactions, and snapshots. Queries and pull Datalog clauses, inputs, rules, aggregates, and pull patterns. History Historical views, as-of, since, and transaction logs.

vevdb.com · 1 images · 26 links

Comments (0)

No comments yet