TessariDBDocs
  • 0.34.2-betalatest
  • 0.34.1-beta
  • 0.34.0-beta
  • 0.33.4-beta
  • 0.33.3-beta
  • 0.33.2-beta
  • 0.33.1-beta
  • 0.33.0-beta
  • 0.32.0-beta

TessariDB

The stack around the model, in one store: eleven engines — documents, graph, full-text, vectors, geometry, key-value, files, time-series, queues, topics and a vault — under one language, one transaction and one binary.

TessariDB is one store with eleven engines: documents, a graph, full-text search, vectors, geometry, a key-value space, file buckets, time-series, queues, topics and a vault. Not eleven services behind a façade — eleven access paths over one substrate, reached through one language and written in one transaction.

engineforenginefor
Documentsrecords, nested and schemaless or declaredKey-valueone value under one key — expiring, counted, bounded
Graphedges between recordsFilesbytes, in chunks
Full-textwords inside text, scoredTime-seriesevents grouped by window, under a declared floor
Vectorssimilarity between embeddingsQueueswork handed out one holder at a time
Geometryshapes on the sphere, in metresTopicsevents every reader sees once, in commit order
Vaultsecrets, sealed before they are stored

The point is not that each exists — plenty of stores have one or two. It is that a question spanning them is one statement rather than a join written in your application against two systems that disagree about what time it is.

What it stands in for, and the trade

A project built around a model rarely needs one data system. It needs search, a database for everything else and a queue; then a cache, a lock, an event log, files, places, relations and somewhere for the secrets it must not leak. Each of those is usually one more service to stand up, upgrade, back up, secure and keep in step with the others — and most projects never load any one of them hard enough to need the specialist.

a project would runhere
a databaserecords — declared or schemaless, joined, in transactions
a search enginefull-text — analysed in five languages, scored, prefix, infix and fuzzy; one search over several fields and tables, with synonyms
a vector index, and a step that re-ranks the twovectors, and ORDER BY FUSE
a cache, a lock, a rate limita space — keys that expire, INCR, SET … IF ABSENT, a limit that evicts
a job queuea queue — claims that lapse when a worker dies
an event loga topic — each reader's position in the store
a geo databasegeometry — radius reads, nearest-first, cells for a map
a graph databasethe graph — edges as records, traversed
object storagea bucket, in the same transaction as the records
somewhere for secretsthe vault — fields sealed before they are stored
a time-series store, an audit trailseries, VERSION and the change feed

Not the fastest at any one of them; enough at all of them. A system built for one job will beat a general store at that job, and nothing here claims otherwise — there is no published benchmark. What the store removes is the cost of running all of them, and the seams between them. It grows with the project on the same binary — in memory, on disk, with followers, automatic failover, tables split by key range, two writers on one range, and nodes that speak only TLS to one another — and where a project outgrows one part of it, the data is one log behind a published protocol and five clients, so that part can move out when the numbers say so. The vault seals declared fields; it is not a general secrets service with leases and rotation.

Why this matters for AI applications

Storing a chunk of text with an embedding beside it is the first week of the problem. What an application asks for afterwards is words and meaning ranked together, and a filter and a traversal and what a record said before somebody edited it — then state for the tools the model calls, a cache for answers that cost money, a queue for the embedding pipeline and events the rest of the product reacts to. Every one of those in a separate system is a dual write nobody can make atomic.

Start with the chunk anyway, because it is the shortest way to see the shape. The embedding is an array of numbers in the record, beside the text it came from, so retrieval is one statement: similarity, a full-text match and an ordinary filter, together.

DEFINE ANALYZER simple FILTERS lowercase, ascii;
DEFINE COLLECTION chunks;
DEFINE FIELD body ON chunks TYPE string ANALYZER simple;
DEFINE INDEX by_body ON chunks FIELDS body SEARCH;
DEFINE INDEX by_at ON chunks FIELDS at VECTOR euclidean;
CREATE chunks = { body: 'Ada Lovelace wrote the first program', doc: 'notes', at: [0.1, 0.0] };
CREATE chunks = { body: 'Grace Hopper wrote the first compiler', doc: 'notes', at: [0.9, 0.1] };
CREATE chunks = { body: 'Ada Lovelace and the analytical engine', doc: 'other', at: [0.15, 0.02] };
SELECT body FROM chunks WHERE body MATCHES 'lovelace' AND doc = 'notes' ORDER BY vector::euclidean(at, [0.1, 0.0]) LIMIT 5;

One record back, reached through an index — a keyword match, a tenancy filter and a nearest-neighbour ordering, resolved together rather than intersected in your application.

What follows from the same shape:

No dual writethe chunk, its embedding, its source document and its edges land in one transaction, or none of them do — there is no reconciliation job because there is nothing to reconcile
Exact unless you ask otherwisea vector read is the exact answer unless the statement says APPROXIMATE, so the ground truth you measure recall against comes from the same store, not a second one
Provenance is a traversala citation is an edge, so which document did this answer come from is a query rather than a column convention
The originals live here toosource files go in a bucket, in the same transaction as the chunks derived from them
The store remembers what it saidVERSION reads it as it stood, so what did it know at the time is a statement — and below what reclamation has left, a read is refused rather than guessed
Catch up, not polla subscriber follows a table and is addressed by position in the log, so it resumes exactly where it stopped (protocol)
Secrets it cannot read backa field declared to the vault is sealed before the record is encoded, so the index, the change feed, the replication log and every backup carry ciphertext
One binaryin memory for a test, on disk for a service, and the same process serves it — nothing to stand up before an experiment

A worked example of all of that in one application is Agent Memory — a second product built on this engine, and the page says which parts of TessariDB it leans on for what.

The aspects worth knowing before you commit

One language over everythingthere is no separate schema language, no migration tool, no admin API — defining a table, reading records, declaring a user and taking a backup are all statements
An index changes the cost, not the answeradding one never changes what a read returns, with a single exception the statement has to spell out: APPROXIMATE
Snapshot isolation, declarednamed in the documentation and in the error taxonomy rather than left to be inferred from behaviour
A refusal has a nameevery one is stable enough to match on, and carries the span in your script — the catalogue lists them
The log is the backup, and the state is tooa restore is a replay, a snapshot carries the current state when the log has been pruned, a script rebuilds the store in its own language, and --verify reads a backup without needing anywhere to put it
Closed by declarationa store with no user is open; declaring the first closes it, for reads as well as writes

Where to start

  • Your first store — from an empty prompt to a record you can read back, in about two minutes.
  • What it is — the shape of the store, in a page.
  • The engines — all eleven, what each had to decide to be exact, and which one answers your question.
  • TessariQL — the language, starting with records.

The rest of it

Getting startedinstall it, run it, connect to it
TessariQLrecords, documents, graphs, joins, search, vectors, geometry, transactions
Keys and filesthe key-value space and the file bucket, in the same transaction as the records
Users and accessthe open store, the three roles, what a grant narrows, and encryption in transit and at rest
Clusteringadding a node, what replicates where, failover, acknowledgement, reads and routing
Running a nodeserving, draining, stopping, backing up, peers
Clientsthe Rust client, the HTTP surface, the wire protocol
Referenceevery statement, function and type, the command line, and the refusals by name

What is true here

Every example on this site is run against the engine before the page ships — in order, against a scratch store, with a block the prose calls refused required to be refused. An example that appears here is an assertion that passes, not a sketch of an intended feature. Many of them are drawn from the engine's conformance corpus, which is the executable definition of the language; the rest are written for the page and held to the same bar. See The examples are executed.

Where a page describes something the engine does not do yet, it says so at the top. There is no third category.

This is 0.34.2-beta — what tessaridb --version answers, and what the published image tessaridb/tessaridb:0.34.2-beta runs. The language and the wire are still moving. The on-disk format is held: a store written by 0.22.0-beta or any release since opens under a newer build and reads back the same.