Features

InvariantDB features

InvariantDB stores what was true, when, and what the system knew when it acted. The catalog below lists the capabilities in the current release, from bitemporal Cypher and provenance to agent memory. Capabilities that are not yet available are listed under Things we don't claim.

On this page

Storage + durability

FeatureSurface
Append-only versioned historyEngine-level; verify with GET /graphs/{name}/audit/verify
Bitemporal versioning on every property (VALID + RECORDED)Cypher AT VALID / AT RECORDED / OVER VALID BETWEEN
Hash-chained write history (each node and relationship write committed through Cypher, /execute or import records the SHA-256 hash of the previous record; schema, index and constraint changes and the legacy POST /write route are not recorded)GET /graphs/{name}/audit/verify returns clean or the first broken record
WORM mode (no API turns it off once engaged): updates and deletes sent through Cypher, MCP tools, /execute and import are refused; creates are accepted. It does not cover the legacy POST /write route on the default graph, schema or index changes, or an administrator dropping the whole graphGET /graphs/{name}/worm, POST /graphs/{name}/worm/engage (Enterprise license)
Schema versioning + history/graphs/{name}/schema/history
Recovery on restartAutomatic; acknowledged writes and index, constraint and schema changes are kept. A write statement interrupted by a crash leaves nothing behind
On-demand full maintenance (repair)POST /graphs/{name}/compact-full
Per-property history walkdb.propertyHistory(nodeId, 'prop')
Online backup + restore (writes continue during a backup; pause writes for an archive of one exact moment)/graphs/{name}/backup + /graphs/{name}/restore

Cypher language

Implements openCypher with bitemporal extensions. Highlights:

FeatureExample
MATCH / WHERE / RETURN / WITHstandard
CREATE / MERGE / DELETE / DETACH DELETEstandard
SET / SET += (map-merge)SET n += {a: 1, b: 2}
AT VALID / AT RECORDED / AS OFMATCH (n) AT VALID '2024-06-01' RETURN n
OVER VALID BETWEEN, OVER RECORDED BETWEENhistory walks across a window
OPTIONAL MATCH with multi-stage carryovernested across WITH boundaries
UNWIND ... CREATE bulk-seed + range()UNWIND range(1, 1000) AS i CREATE (:Node {n: i})
WITH-stage aggregationWITH x, count(*) AS c WHERE c > 5
count(DISTINCT x) / collect(DISTINCT x)dedup-aware aggregates
Pattern comprehensions[(a)-[:KNOWS]->(b) | b.name]
Quantifiers ANY / ALL / NONE / SINGLEWHERE ALL(x IN xs WHERE x > 0)
reduce(acc=init, x IN list | expr)functional fold
shortestPath / allShortestPathspath algorithms in-query
COUNT { MATCH ... } count-subqueryCypher-5
Named paths p = (a)-[r]->(b)length(p), nodes(p), relationships(p)
=~ regex, STARTS WITH, CONTAINStext matching
Inline cosine() / euclidean() / dotProduct()vector similarity in WHERE/RETURN
$name param substitutionanywhere a literal goes, including LIMIT $page
EXPLAIN / EXPLAIN ANALYZE / PROFILEdry-run + with-timing; PROFILE (from 1.4.1) is the same as EXPLAIN ANALYZE
CREATE INDEX (current + historical backfill)property indexes
UNIQUE, NOT NULL, NODE KEY and property type constraints, checked on every writeCREATE CONSTRAINT [name] [IF NOT EXISTS] FOR (n:L) REQUIRE n.p IS UNIQUE / IS NOT NULL / (n.a, n.b) IS NODE KEY / n.p IS :: INTEGER; CALL db.constraints() lists them; CALL db.validateConstraints() checks stored data
Required-relationship constraint, with an optional quote check (from 1.4.2): a node of a label cannot exist without a relationship of a given type to a node of a target label. Checked on current records on every write; not checked at past valid timesCREATE CONSTRAINT [name] FOR (c:Claim) REQUIRE (c)-[:SUPPORTED_BY]->(:Passage) [OPTIONS { quote: true }]; a violation answers 409 CONSTRAINT_VIOLATION and applies nothing
All-or-nothing write statementsAn error, time limit or cancel leaves nothing of the statement; write statements on one graph run one at a time
FeatureSurface
Fulltext search (BM25)gds.fulltextSearch(label, property, query [, k]); from 1.4.3 an analyzer option that indexes every script
Declared full-text indexes (from 1.4.3)db.createFulltextIndex(label, property) and db.fulltext.query(...): phrases, AND / OR / NOT, prefixes, proximity, same sentence or paragraph, exact totals, pages and snippets with offsets; kept current on every write; reads at a past time with history: 'all'. See Cypher →
Vector similarity searchgds.vectorSearch(label, prop, q, k); from 1.4.2.2 a config map with filter (property conditions) and nodeIds (the nodes the search may return), applied before the top k
First-class Vector property typeSchema
vector.similarity(), vector.distance(), vector.dot(); from 1.4.2.2 vector.similarity.cosine() and vector.similarity.euclidean() (Neo4j 5 names)Inline in WHERE / RETURN
Predicate-filtered vector searchCypher WHERE filter + ORDER BY cosine(...) in one query — no external vector DB. See Cypher →
Vector search narrowed by a graph pattern (from 1.4.2.2)MATCH <path> WHERE ... ORDER BY vector.similarity(r.p, $q) DESC LIMIT k scores only the nodes the pattern reaches. See Cypher →
Top-k plan selectionORDER BY vector.similarity(...) DESC LIMIT k keeps only the top k rows while scoring; a WHERE vector.similarity(...) > t filter scores every row it is given
Vector + graph fusiongds.semanticMatchExpand(...)
Embedding model versioning + driftdb.embeddingModelDrift()
Pre-build + cache the vector indexdb.buildVectorIndex(label, prop, metric)

Graph algorithms

AlgorithmSurface
shortestPathgds.shortestPath(source, target) → (path, length); source and target are string ids or id(n)
pageRankgds.pageRank([damping]) → (nodeId, score); damping defaults to 0.85
connectedComponentsgds.connectedComponents() → (nodeId, componentId), weakly connected
degreeCentralitygds.degreeCentrality() → (nodeId, inDegree, outDegree)

Agent memory (AI-first primitives)

Full guide: AI memory.

PrimitiveProcedure(s)
Episodic memory logdb.recordEpisode, db.replayEpisodes
Working-memory consolidationdb.consolidateSession, db.sessionSummaries
Inference provenance + belief revisiondb.recordBelief, db.reviseBelief, db.beliefLineage
Salience decay + reinforcementdb.applySalienceDecay, db.reinforceSalience
Vector + graph fusiongds.semanticMatchExpand
Embedding drift detectiondb.embeddingModelDrift
Property provenance walksdb.propertyProvenance, db.derivedFrom

Compliance

Full guide: Compliance. Vertical mappings: Regulated industries.

PrimitiveSurface
Field-level ACL: for authenticated callers, a property the caller may not read is returned as null or left out, and a search over it is refused; from 1.4.2 a node that hides the searched property from the caller through another of its labels is left out of search results and of their scores; write ACLs are checked only when a Cypher CREATE creates a node (not on MERGE, SET, /execute or import) + hash-chained ACL event log of denied reads in Cypher, refused searches and refused createsSchema-driven; db.aclEvents, db.verifyAclChain()
Purpose binding (GDPR Article 5(1)(b))purpose claim on the caller's JWT, checked against purpose lists in the schema's field ACLs
Per-subject DSAR export (Article 20)db.subjectExport(subject)
Per-property provenancedb.propertyProvenance + db.derivedFrom
Write provenanceprovenance object on POST /cypher and POST /graphs/{name}/cypher requests, or X-Provenance-* headers; the engine also records the authenticated credential as principal: from 1.4.2 for every write of an authenticated request (not for import and other background jobs or the legacy POST /write route), on 1.4.1 and earlier only when the request carries provenance; read with db.propertyProvenance and, from 1.4.2, db.history
Private mode: noised aggregatesAPI-key privacyMode: only expressions built on count, sum or avg may be returned; noise is added and each aggregate spends from the key’s ε budget. This release does not give a differential-privacy guarantee; do not rely on private mode alone to protect individual records
Capability tokensPOST /capabilities/issue (signed, scoped, time-limited)
Compliance bundle export/graphs/{name}/compliance/export (Enterprise license)
Tamper-evidence checksGET /graphs/{name}/audit/verify, db.verifyAclChain(), db.dpVerifyChain()

Server / API

FeatureSurface
HTTP + JSON Cypher endpointPOST /cypher, POST /graphs/{name}/cypher
SchemaGET / POST /graphs/{name}/schema, GET /graphs/{name}/schema/history
Multi-graph registryGET /graphs, POST /graphs, DELETE /graphs/{name}
Request limitsPer-graph concurrency limit (503 with Retry-After) and a per-credential request-rate limit on POST /cypher (429 with Retry-After)
Idempotency keys on write requests (from 1.4.2)Idempotency-Key header on the Cypher, /execute, document and import routes: a resend with the same key returns the first answer and writes nothing. GET /graphs/{name}/idempotency-keys/{key} tells whether a keyed request committed. Keys are kept for 24 hours by default
Per-query timeoutConfigurable at deploy time
Slow query log + counterConfigurable threshold; Prometheus surface
Cooperative yielding (long queries)Configurable throttle threshold
Cursor / streaming readsPOST /graphs/{name}/cursor
POST /graphs/{name}/explainPlan + cost estimate
/healthz / /metrics (Prometheus)Liveness + observability
OpenAPI specGET /openapi.yaml + GET /docs (Swagger UI)
OpenTelemetry tracingOTLP/gRPC export (self-hosted; configured by the operator)

Auth

ModeSurface
Operator-static bearer tokensAuthorization: Bearer <env-token> (constant-time compared)
Runtime-issued API keysgq_<random> prefix; SHA-256 stored, secret shown once
JWT (Cognito-style)Configurable issuer + JWKS URL
HMACPer-request signed header
Capability tokensSigned, scoped, time-limited bearer
Field-level ACL + rolesSchema-declared; principal carries role list
Access policy by label and relationship type (from 1.4.2)db.access.* procedures: roles with allow and deny rules for read, write and grant. For a credential the policy restricts, hidden nodes and relationships are absent from Cypher reads and refused writes answer 403 ACCESS_DENIED. On this release such a credential is refused search, other procedures, temporal reads and the HTTP routes outside Cypher; there are no rules on individual records. See the Cypher reference
Purpose bindingpurpose claim on the caller's JWT, matched against purpose lists in the schema's field ACLs
Graph ownershipGraphs created from the dashboard belong to your tenant; API keys can be limited to a list of graphs
Private modeprivacyMode on API key — only expressions built on count, sum or avg may be returned

SDK

Python (pip install https://sdk.invariantdb.com/python/invariantdb-0.8.0-py3-none-any.whl)

The Python SDK is not published on PyPI. Install it from the URL above.

Node (npm install https://sdk.invariantdb.com/node/invariantdb-0.8.0.tgz)

Same surface, idiomatic to TypeScript.

MCP — Model Context Protocol

Endpoint: https://invariantdb.com/graphs/{name}/mcp (HTTP POST, JSON-RPC 2.0; authenticated with Authorization: Bearer gq_... or OAuth sign-in). Works with MCP clients such as Claude, Cursor and VS Code. 28 tools for Cypher queries and lookups, search, agent memory, documents, lineage, and compliance. From 1.4.2, nine experimental tools for run traces and a shared workspace (off by default) are served where the server operator has turned them on. See the MCP page for client setup.

Operability

FeatureSurface
Prometheus /metrics30+ counters (queries, mutations, ACL events, private-mode counters, integrity ops)
Job lifecycle persistenceLong-running imports survive restart
Per-graph flushPOST /graphs/{name}/flush
Per-graph warm-up/graphs/{name}/warmup
Per-graph backup + restore/graphs/{name}/backup, /restore
Engine info / capabilities/healthz

Things we don't claim

← Quickstart  ·  AI memory →  ·  Regulated industries →  ·  Compliance →