Memtrace · the foundation Persistence layer · live
MemDB

The first database where time
is a first-class citizen.

MemDB is a bi-temporal graph + vector database built from the storage layer up. Every record (every node, every edge, every embedding) knows when it was true. That single architectural decision makes possible a class of queries no other database can answer: replayable, point-in-time, semantic-and-structural retrieval over evolving codebases. In one round-trip. With no index rebuild.

Run the benchmark
8.4×indexing vs ArcadeDB
12.1×graph traversal
0.155msp50 commit
16MBat 100k records
MemDB · bi-temporal record store
3 dims
1 query
01 · The architectural decision

Three properties. No existing database combines them.

Datomic has bi-temporal but no vectors. Pinecone has vectors but treats time as metadata. Neo4j is graph-native but has no vectors. MemDB combines all three at the record-header level. Not a feature flag, a foundational choice.

Property 01

Native graph traversal

Every node and edge is a first-class record. Type-aware traversal: CALLS, DEPENDS_ON, IMPLEMENTS, natively, not via a join table.

Property 02

Native HNSW vectors

Embeddings stored as records, not auxiliary indices. Each vector carries its own bi-temporal header so similarity queries can be replayed at any past timestamp.

Property 03

Bi-temporal record headers

Every record carries valid_at (when this fact became true) and invalid_at (when it stopped). Append-only: nothing is ever overwritten.

The combination

A single as_of_time predicate

Flows uniformly through ANN similarity, graph traversal, and metadata filtering. One query, one round-trip, any point in time.

02 · Under the hood

Every record carries the same 32-byte header.

Vector records, graph nodes, edges, metadata: all share one structure. The visibility rule is uniform: a record is visible at query time T if and only if valid_at ≤ T < invalid_at.

The header

32 bytes in front of every record: vector, node, edge, or property. This is the only place in the database where time lives. Applications above it never see it.

valid_at: when fact became true
invalid_at: when it stopped
transaction_at: when written
still valid (i64::MAX)
PAST NOW FUTURE RECORD HISTORY · TIME → r#0a3c rotateToken → verifyJwt Mon 14:02 LIVE r#0a3d useSession → rotateToken Mon 14:03 r#08f1 rotateToken → oldJwt Fri 09:21 Mon 14:02 r#0728 vec[encryptPwd] · 768d · jina-code Wed 11:05 r#05c1 vec[encryptPwd] v1 as_of_time ◆ SOLID = visible at as_of_time ◆ DASHED = superseded ◆ GREEN = the query timestamp
RecordHeader · Rust · 32 bytesFrom memcore-rs/src/storage/header.rs
struct RecordHeader {
    rid:            u64,    // record identifier
    valid_at:       i64,    // when this fact became true
    invalid_at:     i64,    // when it stopped, i64::MAX = still valid
    transaction_at: i64,    // when this record was written
    episode_id:     u64,    // grouping for atomic multi-record changes
    schema_ver:     u16,
    kind:           u8,
    flags:          u8,
}
03 · The fusion operator

One predicate. Four phases. Zero round-trips.

The as_of_time argument flows through every phase of the query. Vectors, graph hops, metadata filters: all see the same point-in-time view, computed once, returned in milliseconds.

FusionQuery::ann().as_of(T).then_walk(…)

Phase 1

Filter HNSW candidates

Vectors invalid at T excluded before distance computation, so no wasted similarity work.

Phase 2

Walk the graph

Multi-hop from seed candidates. Each node and edge filtered by the same valid_at ≤ T < invalid_at.

Phase 3

Apply metadata filters

Property predicates use the value of the property valid at T, not the current value.

Phase 4

Rerank & return

Final score combines similarity, graph distance, and any application signal. Ranked, replayable, deterministic.

Single round-trip · no index rebuild · deterministic at any past timestamp 0.155ms p50 commit · 0.907ms p99 · 48,566 samples
04 · Engineering numbers

Reproducible from the repo. Every one.

Measured on Apple Silicon, runnable via cargo bench. Result JSONs with commit SHA, hardware, kernel, and HDR histogram raw data.

Cold start · 10k nodes
4.0ms

Process spawn → first answerable query. Spec target was 500ms. 71× under target.

WAL commit · single page
0.155ms

p50 across 48,566 iterations. Spec target was 3ms. 3.3× under target.

Resident memory · 100k records
16.84MB

Peak RSS. Spec target was 75 MB. 22% of budget. Fits on a laptop alongside the agent.

vs ArcadeDB · indexing
8.4×

Plus 12.1× faster graph traversal, 5.7× faster ANN. Time-travel: infinite. They can't.

05 · Why nothing else fits

Everyone has two of three. No one has all three.

The patent surface is the unified as_of_time predicate threaded through ANN + graph + metadata. Provisional patent filing in flight.

Database
Native graph
Native vectors
Bi-temporal
Time-travel query
Pinecone
No
Native
Metadata only
Rebuild required
Neo4j
Native
~ Plugin
No
Snapshot tooling
Datomic
~ Datalog
No
Native
~ Relational only
ArcadeDB
Native
Native
No
Not possible
HelixDB
Native
Native
No
Not possible
MemDB
Native
Native (HNSW)
Record-header
Single query
Build on it

Memtrace’s code map runs on it. The Fleet writes to it.
MemDB is the memory inside Memtrace
that makes the whole thing possible.

Audit logging. Time-travel debugging. Regulatory compliance for ML. MemDB, the memory with time built in inside Memtrace, is the primitive everything else is built on. That’s the moat.

MemDB · bi-temporal · 8.4× · 0.155ms Code map · runs on MemDB → Fleet · writes to MemDB →