Self-hosted service
terminusdb/terminusdb avatar
terminusdb/terminusdb

TerminusDB: a graph database that treats every write as a commit

TerminusDB is a distributed, collaborative database designed for building, sharing, versioning, and reasoning on structured data.

3,435 stars158 forksPrologApache-2.0

At a glance

What is it?
A Prolog and Rust database where JSON and JSON-LD documents live in a knowledge graph, every update becomes a revision, and branches merge the way Git branches do. Strong opinions about collaboration, some rough edges around the dashboard.
Who is it for?
TerminusDB earns its place when the data is a graph and the reason you want it is provenance: schema-constrained documents, a commit per change, branch and merge, and queries against any point in history. It is written in Prolog with Rust on the hot paths, and the datalog engine is a genuine differentiator rather than a wrapper over Cypher.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Prolog, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 9, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Git for data is the product, not a feature list

TerminusDB's own framing is the shortest description of it: a distributed database with a collaboration model, git for data. The README then lists the operations that framing implies, and they are the ones a Git user already knows. Every update produces a commit you can track over time. The difference between two commits can be interpreted as a patch between states. Nodes communicate by pushing and pulling those diffs with familiar git-like operations. And you can query any state of the database at any commit, which the README calls a time-travel query.

That last capability is the one that changes how you build on a database. If your use case is compliance, audit, provenance or any workflow where you have to answer what the data looked like on a given date, the conventional answer is to rebuild history from an event log or a temporal table. Here the history is the storage model, so a point-in-time query is a first-class read rather than a reconstruction.

The data model underneath is JSON and JSON-LD documents linked into a semantic knowledge graph and reached through a document API. The project positions itself as a system of record rather than as a cache or a search index, and the repository topics agree: document-database, knowledge-graphs, linked-data, revision-control and immutable all appear there, alongside acid and headless-cms, which tells you the intended audience spans from compliance work to content backends.

Storage is on disk under `storage/`, and the compose file binds `./storage` into the container so your data survives image upgrades.

Four query languages, and why that cuts both ways

TerminusDB lets you reach the same data through REST, GraphQL, WOQL and RDF with a closed world assumption. The README is deliberate about framing each one as a proper graph query language with deep link discovery and path queries, and WOQL as a goal-seeking problem-solving toolbox with triples across and within documents, path queries and variable unification.

WOQL is the one worth learning first. It is Datalog, which means a query states relationships and the engine unifies variables to find answers. For graph work that is a better fit than imperative traversal, and it is the language the schema and reasoning features are built around. The README also lists built-in unification, path queries and a datalog logic engine as a headline feature, and the topics include acid, which pairs with the commitment model rather than with the query syntax.

Supporting four query surfaces is genuinely useful when you are integrating: a GraphQL endpoint saves you writing a resolver layer, REST saves you writing a client, and WOQL is there when the question is genuinely relational over the graph. It also means four sets of edge cases to learn and a larger surface for version-specific bugs, and the release history shows where those land, with fixes in v12.0.6 for `@ref` capture resolution through TaggedUnion variants and for dict, list and number handling in SwapValue patches.

If you are evaluating this against Neo4j, note that the query language is the largest difference. There is no Cypher. If your team already writes Cypher, that is the cost you are actually pricing, and it is larger than the storage layer underneath.

Version 12 is about arithmetic and time, not new query syntax

The README's section on what is new in version 12 is unusually specific about mathematics, and the specificity is the useful part. Arbitrary precision xsd:decimal means rational precision decimal arithmetic, including high precision JSON decimals over the wire for JSON, GraphQL and WOQL, following ISO/IEC 21778:2017. On top of that sits ISO8601 Allen interval algebra for temporal reasoning, storage and lifecycle management of XSD time datatypes.

Together those two features describe a database aimed at financial and industrial records where 0.1 plus 0.2 and the length of a contract matter. Arbitrary precision decimals are the difference between a total that is exactly right and one that is right to fifteen places. Allen interval algebra is the difference between knowing two date ranges overlap and knowing how they relate, including containment and the identity of shared endpoints. Range queries over succinct data complete the picture, promising constant time retrieval over arbitrary size ordered data, which is what you want for knowledge graph processing across timestamp, numeric and interval ranges.

The README credits the DFRNT maintainers with this work and notes new maintainers and an enterprise version, which is worth knowing when you are choosing a long-term home for data. The v12.0.7 release on 2026-08-10 continues the thread with an `unfold` parameter on the diff API, the ability to apply explicit diffs, and an SWI-Prolog upgrade to 10.0.2 with the `jwt` implementation backed by Rust.

One inconsistency to be aware of: the README's version 12 section links to the v12.0.5 release tag, while v12.0.6 and v12.0.7 have shipped since. The feature descriptions still apply, but the tag in that link is behind the current release.

Schema annotations that do real work

Schema constraints are listed as a headline feature, with the promise of enforcing data quality and consistency including for advanced typing. The visible mechanism is a set of annotations that change how documents are stored, queried and merged, and the release notes show the ones being actively extended.

`@unfoldable` unfolds subdocuments within a frame so all relevant data arrives in one place, which is a query ergonomics feature rather than a storage change. `@metadata` support includes additional metadata in document frames, including Markdown-formatted data. `@shared` is the interesting one: it is a class-level annotation for cascade-deleted shared documents, added in v12.0.6, and `@shared` was also added to the Rust change detection algorithm in v12.0.7. Shared documents that cascade on delete are exactly the kind of thing where a naive merge produces silent data loss, so having the annotation in both the type system and the change detection layer suggests the team treated it as a correctness problem rather than a feature request.

The bugfix list in the same releases points at where the sharp edges are. v12.0.6 fixes silent document loss for non-ASCII characters in the document API and a false patch conflict on xsd:decimal properties, and v12.0.7 fixes RFC 3986 scheme detection in `uri_has_protocol/1`. Silent loss and false conflicts are both merge-adjacent failures, which is consistent with a system whose differentiator is collaborative editing.

If your data has shared, cascade-deleted subdocuments or decimal money, treat those two fixes as the reason to be on a current release rather than a curiosity.

Getting it running with Docker, and which port you actually get

The README points developers at a ten minute Docker manual and the `terminusdb/terminusdb-server` image, and tells you deployments to copy `docker-compose.yml` from the repository. The one required configuration step is a password in a `.env` file:

shell
# Database administrator's password (required)
TERMINUSDB_ADMIN_PASS=

The README is emphatic that `TERMINUSDB_ADMIN_PASS` is mandatory. The repository's `.env.example` carries the same variable plus an optional `OPENAI_KEY` and a `BUFFER_AMOUNT` that controls how many pages the vector database buffers, which is a hint that the compose stack expects an indexing sidecar.

The compose file confirms that. It defines a `terminusdb-server` service, a `vectorlink` semantic indexer image, and a `change-request-api` service, so what you start with `docker compose up` is a three-service stack rather than a single database process. It also sets `TERMINUSDB_INSECURE_USER_HEADER=X-User-Forward` with the enabled flag turned on, and the comment above those lines is unambiguous: disable them in production or put an authentication gateway in front. That is a useful default for local work and a genuine hazard if you copy the file to a server without reading it.

Now the port, because it is where a first run tends to trip. The README says you can view TerminusDB running by default at `localhost:6363`. The compose file sets `TERMINUSDB_SERVER_PORT=6363` inside the container but publishes `6364:6363` on the host. The instructions at the top of the compose file tell you to connect to `localhost:6363`, and the README agrees, so on the published port mapping you reach the server on host port 6364. Both values are in the repository and they do not agree; check which one your compose file publishes before you conclude the server failed to start.

Prolog and Rust, and what the build actually needs

The repository's primary language is Prolog, which is the single most important fact for anyone considering building it. The `Dockerfile` builds on an official `swipl` image with `ARG SWIPL_VERSION=10.0.2`, so you do not install Prolog yourself, and the `Makefile` defaults the same version with a comment noting it was previously 9.2.9. Rust is the second implementation language, used for the JWT implementation and for change detection, and the Dockerfile installs Rust via rustup with a minimal profile before building `src/rust`.

The pack dependency step is the part that will take longest on a cold build. It installs build-essential, libssl-dev, pkg-config, clang, m4, libgmp-dev, protobuf-compiler and libprotobuf-dev, then copies `distribution/Makefile.deps` and runs make to pull the SWI-Prolog pack dependencies. That is a real toolchain, not a single binary download, and the v12.0.7 release added documentation for protoc and make install-deps as macOS build prerequisites, which is a reasonable thing for the project to have just added.

The Makefile's everyday targets are small and legible. `make` delegates to `distribution/Makefile.prolog` to build the binary. `make dev` produces a macOS-friendly build with libraries left unstripped and JWT enabled by default so integration tests work, and it first generates a development RSA key pair through `node tests/generate-dev-jwks.js`. There is also a Snap package that provides both the client and the server, and the README positions that combination as the way to try the command line tool for ML and AI work needing deterministic symbolic processing.

For the UI, the README is direct: the complete modeller interface is DFRNT Studio, and the dashboard still in the repository tree is now deprecated and described as buggy. A `dashboard/` directory exists at the top level and the Makefile still writes a dev JWKS file into `dashboard/assets/test-jwks.json`, so the code is there even though the README steers you away from it.

Editorial conclusion

TerminusDB earns its place when the data is a graph and the reason you want it is provenance: schema-constrained documents, a commit per change, branch and merge, and queries against any point in history. It is written in Prolog with Rust on the hot paths, and the datalog engine is a genuine differentiator rather than a wrapper over Cypher. The costs are equally concrete. It is a young version line whose dashboard the README itself calls deprecated and buggy, whose host port mapping in `docker-compose.yml` disagrees with the port the README tells you to visit, and whose operational documentation lives on terminusdb.org rather than in the repository. Start with the ten minute Docker path on `localhost:6363`, confirm which host port your compose file actually publishes, and only then decide whether the query model fits your problem.

Frequently asked questions

What does git for data mean in TerminusDB?

Every update to a document produces a commit you can track over time, the difference between two commits can be interpreted as a patch, and nodes exchange those diffs with push, pull and clone operations. You can also query the database as it was at any past commit, so history is part of the storage model rather than something rebuilt from an event log.

What query language does TerminusDB use?

You can reach the same data through REST, GraphQL, WOQL and RDF with a closed world assumption. WOQL is the Datalog-based language with built-in unification and path queries, and it is the one the schema and reasoning features are built around. There is no Cypher equivalent.

How do I run TerminusDB locally with Docker?

Copy `docker-compose.yml` from the repository, create a `.env` file containing the mandatory `TERMINUSDB_ADMIN_PASS`, and run `docker compose up`. The stack starts the server plus a vectorlink indexer and a change request API. Be aware that the compose file publishes host port 6364 to the container's 6363 even though the README text points you at `localhost:6363`.

Does TerminusDB support decimal precision and temporal reasoning?

Version 12 adds arbitrary precision xsd:decimal arithmetic following ISO/IEC 21778:2017, including high precision decimals over the wire for JSON, GraphQL and WOQL, plus ISO8601 Allen interval algebra for temporal reasoning over XSD time datatypes. Both are aimed at financial and industrial records where exact totals and interval relationships matter.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. terminusdb/terminusdb on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/terminusdb-terminusdb.svg)](https://hysenlabs.com/projects/terminusdb-terminusdb)