Skip to main content

Concepts

Archive​

When backups are enabled, every bank's write-ahead log and base snapshots are copied to a separate backup bucket, ideally in another account with a credential that cannot delete. A bank can be restored to a log position or a point in time ("just before the bad import at 09:14"), and every restore is verified before traffic is routed to it. See Guarantees.

Arm​

One of the four searches Memlake runs for a recall: by meaning (vector), by keyword (BM25), through relationships (graph) and through time. Each arm returns its own raw score and rank for every candidate. An arm that did not find a candidate reports it as absent, not as a score of zero. See Retrieval.

Backpressure​

If writes arrive faster than they can be indexed, the un-indexed part of the log grows, and every query has to scan it. Memlake caps that in bytes: once a bank's un-indexed backlog passes a limit, new writes get a retryable error until indexing catches up. A rejected write was never acknowledged, so nothing is lost.

Bank​

A Hindsight memory bank: an isolated set of memories, usually per agent, user or project. In Memlake, each bank is a prefix in its organization's bucket, with its own write-ahead log, segments and manifest. Smaller, well-scoped banks give faster and cheaper queries, since per-query cost grows with bank size — sublinearly for vector search, and with segment count for bytes read.

Cache hierarchy​

Memlake query nodes cache object-storage blocks in memory and on local NVMe, keyed by object path. Because every data object is immutable and lives under a unique path, cached blocks never need invalidation. Dropping the cache changes latency, never results. The memory and disk caches each have a fixed budget, derived from the query node's memory limit and cache volume.

Cold start​

The first query to a bank on a query node opens it, loading its index metadata from object storage (8.6 s at p95 for a 10M-memory bank), and data blocks are read from the bucket until they are cached. Query nodes warm a bank in the background when they open it or pick up a new index, and you can send one recall ahead of a busy period to start the warm-up. See Architecture.

Compaction​

An index update usually adds a small segment. Compaction merges small segments in the background, so the number of segments stays bounded, with the bank size divided by the maximum segment size as its floor. Compaction memory is bounded by configuration, not by bank size.

Compute-storage separation​

Durable memory state lives only in object storage; query nodes are compute and cache. (Hindsight's small operational data stays in Postgres.) Serving capacity scales by adding query nodes, storage scales with the bucket, and neither needs the other to grow. Indexing runs as a separate workload from queries and is scheduled away from query query nodes.

Conditional writes​

The only coordination mechanism in Memlake. A conditional create (If-None-Match: *) claims a write-ahead log slot; a conditional replace (If-Match: <etag>) advances the head pointer or swaps the manifest. A writer that loses a race re-reads and retries. There are no locks, and no lease that correctness depends on. Memlake ships a tool to certify that an object store honours both correctly.

Entity​

A person, place, organization or thing that memories mention. Memlake keeps an entity registry per bank, resolves names to entities on write, and stores each memory's entities with the memory itself, which the graph arm uses to find related memories.

Garbage collection​

Nothing in object storage is overwritten, so obsolete files — indexed log entries, merged segments, the losing side of a race — are deleted later. Garbage collection deletes only what the current manifest no longer references, and only after a safety window (15 minutes by default) measured on the object store's own clock.

Group commit​

Concurrent writes to the same bank can share one head-pointer update over a short window. Each write is still its own immutable WAL object; grouping reduces contention on the bank's one mutable head object. It is off by default and set per query node.

Head pointer​

A small object per bank that covers every acknowledged log position. It only moves forward, and it is advanced before a write is acknowledged. Every query checks it to guarantee it sees the latest data; concurrent queries share one read.

Index cursor​

The highest write-ahead log position that has been built into a segment. Queries read segments for everything up to the cursor, and scan the log directly for everything between the cursor and the head pointer.

Indexer​

A query node that turns new log entries into segments and runs compaction. Indexers run as a separate workload, scheduled away from the query nodes that answer queries, and any indexer can index any bank. See Indexing.

Indexing​

Turning new write-ahead log entries into a segment and publishing it. Indexing runs asynchronously on indexer query nodes; its cost depends on how much is new, not on how large the bank is. Memories are searchable before they are indexed.

IVF​

Inverted-file index: vectors are grouped into clusters around centroids, and a query scans only the clusters nearest to it. Memlake's vector search is IVF over RaBitQ codes, with exact reranking. Finding candidates this way is approximate; reranking them is exact.

Log-structured merge (LSM)​

The storage design Memlake uses: writes are appended to a log, indexed into immutable segments, and merged by compaction. Updates and deletes are recorded as newer entries that hide older copies, resolved at query time. It suits object storage, where files cannot be modified in place.

Manifest​

The one object per bank that lists its live segments and index cursor. Publishing a new segment is a conditional replace of the manifest, so a reader always sees a complete set of segments or the previous one — never a mix.

Memory​

One record in a bank: text, an embedding, a memory type, tags, timestamps, entities, and links to other memories. The embedding is stored separately from the rest of the record, as quantized codes for scanning and exact values for reranking.

Memory type​

Hindsight's kinds of memory — world facts, experiences and observations. Each type is its own independent index inside a segment, so one type's statistics never skew another's ranking.

Operational data​

What Hindsight keeps in Postgres when memories are on Memlake: banks and their settings, the queue of background jobs, the audit log. It is small and relational, and holds no memories.

RaBitQ​

The vector compression Memlake uses for the first pass of vector search: about 60 bytes per 384-dimension embedding, 25× smaller than the original. On BEIR it finds the same top 10 as 8-bit vectors. The best candidates are then reranked with exact vectors.

Ranking policy​

How Hindsight turns the four searches' results into one ranked list: fusion, cross-encoder reranking, boosts, score floors and the token budget. Hindsight sends it with every recall, and Memlake applies it next to the data, so policy changes need no reindexing.

Read-your-writes​

A write is visible to the very next query, from any query node, as soon as it is acknowledged. Memlake achieves this by scanning the un-indexed part of the log at query time rather than waiting for indexing.

Segment​

An immutable, self-contained index over a slice of a bank's memories, with one sub-index per memory type: vector clusters, a full-text index, an entity index, a time index and reverse links. A bank is a stack of segments plus the un-indexed log.

Segment routing​

An optional setting for large banks. Instead of searching every segment, the vector arm scores segments by their centroids and searches only the nearest few, which cuts the bytes read and the memory held per query. It applies to the vector arm only and is off by default.

Query node​

A stateless Memlake process that answers queries for any bank from a cache of the bucket, in memory and on local NVMe. Banks are routed to the same query node to keep its cache warm; losing a query node costs latency, never data. Also called a serve node.

Organization bucket​

Each organization's memories live in their own object-storage bucket, named from the organization ID and a per-deployment salt. The bucket is the boundary for access policy, encryption and deletion. Deleting an organization empties and removes its bucket. Copies in the backup bucket are not removed by organization deletion and follow the backup retention policy.

WAL​

The write-ahead log. Each write is one immutable object under the bank's wal/ prefix, numbered in order. It is the source of truth for recent writes, and is read directly by queries until it is indexed. See Writes.