One database is enough
The default architecture for a memory system in 2026 is a small distributed system: a vector database for embeddings, a graph database for relationships, a search engine for keywords, Postgres for everything else, and glue code to keep all four in rough agreement. Illumina runs the whole memory engine in one PostgreSQL database.
What Postgres is doing
Four workloads, one instance:
- Semantic search — pgvector
vector(384)columns with HNSW indexes over the embeddings. - Lexical search — BM25 ranking over native
tsvector, which handles ticket numbers and exact phrases that embeddings fumble. - Entity matching — pg_trgm trigram similarity, so "Postgres", "postgres", and "PostgreSQL" resolve to the same entity without a hand-tuned alias list.
- The knowledge graph — plain relational tables of typed memory links, traversed with recursive and lateral SQL.
That last one raises eyebrows. Graph traversal in SQL sounds like a compromise until you write it down:
WITH RECURSIVE linked AS (
SELECT target_id, link_type, 1 AS depth
FROM memory_links
WHERE source_id = $1
UNION ALL
SELECT ml.target_id, ml.link_type, linked.depth + 1
FROM memory_links ml
JOIN linked ON ml.source_id = linked.target_id
WHERE linked.depth < 2
)
SELECT DISTINCT target_id, link_type FROM linked;
Two-hop link expansion in a recursive CTE, planned and executed by the same engine that runs the vector and BM25 queries. Memory graphs are wide and shallow, and for wide-and-shallow traversal a dedicated graph engine buys you an extra deployment, an extra query language, and a sync pipeline. It does not buy you speed you can measure.
One transaction boundary
Keeping every retrieval arm in one database changes failure behavior. A recall that fans out across semantic, lexical, and graph candidates runs against one query planner inside one consistency domain. There is no window where the vector store has a fact the graph store has not heard about, because they are the same store. A cross-backend sync job cannot fall behind, because there is no cross-backend sync job.
Operations get simpler in the same stroke. One backup covers facts, embeddings, links, and full-text indexes together. One connection string. One thing to monitor at 3 a.m.
Bring your own Postgres
Illumina does not need a managed flavor of anything. Point DATABASE_URL at any PostgreSQL instance with the vector and pg_trgm extensions enabled, and migrations run at boot. Your existing RDS, your Cloud SQL, the Postgres already running in your cluster: all fine.
Files and documents are the one exception to single-store, and only halfway. Uploads go to S3-compatible object storage, and deployments without object storage fall back to a Postgres column. The fallback keeps the minimum viable deployment at exactly two dependencies: a Postgres database and the Illumina binary.
Boring on purpose
Postgres has thirty years of production behavior behind it. Your team already knows how to back it up, replicate it, tune it, and read its query plans. A memory system holds the record of how your organization thinks, and that record should sit in the most boring, best-understood database available. We built the interesting parts on top.