TessariDB
Get started

Database engine · Rust · one binary

The stack around the model, in one store.

Eleven engines. One transaction. One thing to run.

The database, the search engine, the vector index, the cache, the queues, the event log, the map, the graph, the files and the secrets an AI application needs — one binary, one language, one transaction. Not the fastest at any one of them. Enough at all of them, for the projects that never push one to its limit.

Also built on it

TessariDB S3 is S3-compatible object storage in Rust. Object bytes erasure-coded across your nodes, zones and regions; every bucket, key, version and policy a transaction in TessariDB.

  • Unmodified S3 clients and SDKs
  • Reed-Solomon erasure sets across zones
  • Regions, each a cluster of its own
  • Versioning, Object Lock, lifecycle
  • Events into a TessariDB topic
  • A console that keeps a record

pre-alpha · BUSL-1.1 server, Apache-2.0 Rust SDK and CLI

s3.tessaridb.com →

The read, in full

A keyword match, a filter and a nearest neighbour.

One statement, resolved by the store rather than intersected in your application. The answer below is the node’s own — including the trailer, which is how it reports that the read went through an index rather than across a scan.

A keyword match, a filter and a nearest neighbourtessariql
DEFINE INDEX by_body ON chunks FIELDS body SEARCH;
DEFINE INDEX by_at ON chunks FIELDS at VECTOR euclidean;

SELECT body FROM chunks
WHERE body MATCHES 'lovelace' AND doc = 'notes'
ORDER BY vector::euclidean(at, [0.1, 0.0])
LIMIT 5;
the node answers
1: { body: 'Ada Lovelace wrote the first program' }
(1 record(s), via index)

The shape of the problem

A dozen tools, and the seams between them.

A project built around a model almost always needs search, a database for everything else, and a queue. Then a cache, a lock, an event log, files, a map of where things are, the relations between them, and a place for the secrets it must not leak. Each is good at its own job. Standing all of them up, upgrading them, backing them up and keeping them in step is the job nobody planned for — and most projects never load any one of them hard enough to need the specialist.

TessariDB is eleven access paths over one substrate — not eleven services behind a façade. A question that spans them is one statement, and a write that spans them is one transaction, rather than an intersection you compute in application code against systems that disagree about what time it is.

A database

Records — declared or schemaless, joined, in transactions

A search engine

Full-text in five languages: scored, prefix, infix, fuzzy — one search over many tables

A vector index

Nearest neighbours, exact unless you ask otherwise

A re-ranking step

ORDER BY FUSE — words, meaning and place by rank

A cache, a lock

Keys that expire, counters, a limit that evicts, SET … IF ABSENT

A job queue

Claims that lapse when a worker dies

An event log

Topics, with each reader's position in the store

A geo database

Shapes, radius reads, nearest-first, cells for a map

A graph database

Edges as records, traversed from any of them

Object storage

Files, in the same transaction as their records

A place for secrets

Fields sealed before they are stored

Time-series, an audit trail

Windows, a retention floor, VERSION and a change feed

The seam is sharpest where retrieval lives: a vector database, a document store, a search index and something holding the originals, kept in step by a write that has to land in four places.

Documents

Records, nested, schemaless or declared

Graph

Edges between records, traversed

Full-text

Words inside text, scored

Vectors

Similarity between embeddings

Geometry

Shapes on the sphere, in metres

Key-value

One value under one key — expiring, counted, bounded

Files

Bytes, in chunks

Time-series

Events in the order they happened, windowed and rolled up

Queues

Work handed out one holder at a time

Topics

Events every reader sees once, in commit order

Vault

Secrets, sealed before they are stored

Every engine, and what it costs →

For AI applications

What follows from the same shape.

No dual write

The record, its embedding, the document it came from and the edges between them land in one transaction, or none of them do. There is no reconciliation job because there is nothing to reconcile.

Exact unless you ask otherwise

A vector read is the exact answer until the statement says APPROXIMATE out loud. The ground truth you measure recall against comes from the same store as the answer, not a second one.

Provenance is a traversal

A citation is an edge, so which document did this answer come from is a query rather than a column convention half the pipeline forgets to fill in. The originals go in a bucket in the same transaction, so the thing you cite and the thing you chunked cannot drift apart.

The store remembers what it said

VERSION reads the store as it stood, so why did the agent answer that last Tuesday is a statement rather than an archaeology project. It goes back as far as reclamation has left, and below that a read is refused rather than answered from whatever happens to remain.

Catch up, do not poll

A subscriber follows a table over the wire and is addressed by position in the log, not by a timestamp — so it resumes exactly where it stopped, and starting from zero replays everything the log still holds.

Secrets it cannot read back

A field declared to the vault is sealed before the record is encoded. The index, the change feed, the replication log and every backup carry ciphertext, so the credentials an agent works with are not one careless SELECT away from a transcript.

The whole argument, with the statements →

The trade, said out loud

Not the fastest at any one thing. Enough at all of them.

A specialist built for one job will beat a general store at that job, and nothing here pretends otherwise — there is no benchmark on this site, because none has been measured and published. What most projects pay for is not the last fraction of one system’s speed. It is running eleven of them: their versions, their backups, their auth models, and the reconciliation between them. That is the cost this store removes.

It grows with the project. In memory for a test, a directory on disk for a service, followers for copies, automatic failover, tables split by key range across machines, and two writers on one range — the same binary at every step. The limits are stated where they apply: a table is split only if it was declared split, a split moves no record already written, and the largest shard fits one machine.

A project may one day outgrow one engine of it. The data is one log behind a published protocol and five clients, so moving one workload out is a decision you take then — not a cost you pay on the first day. When one store is the wrong answer →

Stream ingestion, from a topic or from a broker

Read a topic into a table, each message once.

One statement declares a consumer — which topic, which group, how a message becomes a record and where it lands — and the node runs it, starts it again after a restart and reports on it. No connector beside the database, and no worker to keep alive.

When the topic is one of the store’s own, the guarantee is exactly once into the store: the group read, the record writes and the acknowledgement commit in one transaction, so a crash or a refused commit leaves the message unread and nothing written.

A topic, read into a tabletessariql
DEFINE TOPIC CONSUMER orders_in
    FROM orders
    GROUP 'into-rows'
    INTO order_rows
    IDENTITY order_id
    MAP amount AS total
    ON FAILURE quarantine;

From a Kafka broker you already run, DEFINE KAFKA CONSUMER reads the same way — and the guarantee changes, because the broker’s offset is a second commit in a second system: at-least-once, applied idempotently by record identity. The store commit goes before the offset commit, which chooses duplicates over loss, and IDENTITY is what makes a duplicate land on the record it already wrote.

Every clause, and what each one settles →

Getting it running

One binary. No cluster to stand up first.

In memory for a test, on disk for a service, and the same process serves it over the wire and over HTTP. There is nothing to provision before an experiment, which is the difference between trying this today and putting it on a list.

The published image asks for nothing at all — no repository access, no toolchain, no C++ compiler.

From nothing to a first answershell
docker run -p 9080:9080 -p 8000:8000 tessaridb/tessaridb

tessaridb                     # or the binary: a store in memory
tessaridb ./data              # a store on disk
tessaridb ./data --serve 127.0.0.1:7654

Try it against your own data.

Free in production, including inside a commercial company. The one restriction is reselling it to third parties as a database service.