cargo doc -p <crate> --no-deps --open).
Notes:
- Embedded by default. A plain build runs entirely locally: LanceDB vector
index (on disk), embedded Ladybug (graph), SQLite (relational), local file
storage. The in-memory brute-force vector index is used on Android or with
VECTOR_DB_URL=:memory:. - Feature gates.
lancedb,pgvector,pggraph/postgres,onnx,ladybug, and thehf-tokenizer/tiktokencounters are cargo features, on by default incognee/cognee-cli(as isbedrock) — see Architecture: feature strategy. - pgvector indexing. Each collection gets an HNSW index when it is created,
over
vector::halfvec(dim)withhalfvec_cosine_opsandm = 24, ef_construction = 128(tunable — see Configuration: pgvector index tuning), so similarity search is not a sequential scan. The column itself staysvector(the Python SDK’s schema): only candidate selection sees fp16, and scores are the full-precision distance, re-sorted. Each search raiseshnsw.ef_searchto cover its owntop_k(an HNSW scan returns at mostef_searchrows, default 40, and then stops — a largerLIMITis otherwise silently unmet) and runs withhnsw.iterative_scan = relaxed_order, which keeps scanning until theLIMITis met over dead tuples and tightly clustered vectors. Two pgvector version floors, both probed. The adapter readspg_extension.extversiononce when it connects.hnsw.iterative_scanneeds pgvector 0.8+; below that the setting is simply not sent, so searches do not iterate but do not fail.halfvecneeds 0.7.0+ (CREATE EXTENSION IF NOT EXISTS vectordoes not upgrade a database that already carries 0.5.x or 0.6.x); below it the adapter logs a warning and puts both the index and the search ordering back on full-precisionvector/vector_cosine_ops(under the legacy<coll>_vector_hnswname) — a larger index and slower scans, identical results. To move such a store onto the half-precision index, install a pgvector 0.7+ binary, runALTER EXTENSION vector UPDATE, and thencognee-cli vector-reindex. Three exceptions, and in all three the candidate ordering drops back to full-precisionvectorand the scan is exact: collections wider than 2000 dimensions are not indexed; atop_kabove 1000 exceeds the largestef_searchpgvector accepts; and a collection whose index is dropped for a bulk-load scope (see bulk loads below) is indexless until the scope ends. The 2000-dimension ceiling is this adapter’s choice, not pgvector’s limit (the half-precision index allows 4000): at 3072 dimensions an exact scan measured faster than the HNSW index on uniform random vectors, sotext-embedding-3-largecollections keep the exact scan for now.search_similar_filteredstays exact filter-then-limit, but no longer by disabling index scans: each collection carries a GIN index overcognee_vector_set_names(metadata)(a function withnode_filter’s exact semantics), and the filter is&&(OR) /@>(AND) against it, so the membership predicate is an index lookup while the ordering keeps the HNSW post-filtering scan out. - pgvector bulk loads.
VectorDB::begin_bulk_load/end_bulk_load(a nestable, no-op-by-default hint that cognify wraps a pipeline run in) let the adapter stop maintaining an HNSW index row by row during a load: once the points written to a collection inside the scope reach 25% of its live row count its index is dropped, and it is built once — in parallel, under a sizedmaintenance_work_mem— when the last scope ends, followed by anANALYZEof every collection written. Because the threshold counts live rows, an append load defers at about a third of the collection’s starting size and an all-overwrite load at a quarter; the live count is re-read only when the cached one cannot decide. A caller that splits one logical write into severalindex_pointscalls (cognify does, in ~16 MiB windows) callsVectorDB::announce_bulk_writefirst, so the first window is decided as one call of the whole write would have been; the hint lapses when the innermost scope ends and is a no-op by default. A collection without its index is still correct: a search of it runs with index scans off and orders by the full-precision distance, so it is an exact scan returning the true top k. An interrupted load (a crash, a process killed betweenbeginandend) leaves every written row in place and searchable, and the one repair iscognee-cli vector-reindex/create_missing_vector_indexes(), which is idempotent. Collections created before per-collection HNSW indexing existed have only their primary key, and so does any collection whose index build failed — creation is best-effort (it logs a warning and continues, because failing there would leave the table created and unregistered), so pgvector too old for thehnswaccess method, a restricted role or too littlemaintenance_work_memall yield a working, silently sequential-scan collection.cognee-cli vector-reindexbackfills both cases withCREATE INDEX CONCURRENTLY(online, idempotent, and it rebuilds an index left invalid by an interrupted build); embedders can callPgVectorAdapter::create_missing_vector_indexes()directly, or reach it throughVectorDB::create_missing_vector_indexes()on any backend — it defaults to a no-op returning0for the ones that have no such index. It is not automatic: building HNSW over a large collection is expensive, so the operator chooses when. - Upgrading an existing pgvector store. The halfvec index is a new index
under a new name (
<coll>_halfvec_hnsw), so a store built by an older version carries the old full-precision<coll>_vector_hnsw, which the halfvec-ordered searches no longer use. Results stay correct — those searches fall back to a sequential scan and a sort, which returns the true top k — but every search on such a store is that scan, with no error. The adapter therefore warns once per collection, the first time it touches one, naming the collection andvector-reindex.cognee-cli vector-reindexis the repair: it builds<coll>_halfvec_hnswwithCREATE INDEX CONCURRENTLYand then drops the superseded<coll>_vector_hnsw(CONCURRENTLYas well, and only once the new index is confirmed valid — on a pgvector below 0.7 that name is the active index, so there it is left alone). Until then every upsert pays two HNSW inserts. The bulk-load path never drops the legacy index itself. The same name change applies to a collection whose name is longer than 50 bytes: index names now reserve room for their suffix and trim the collection part, so such a collection’s index name changes.cognee-cli vector-reindexbuilds the index under the new name; an index under an old trimmed name is not recognised as superseded and is left on disk for the operator to drop. - Postgres graph tables.
PgGraphAdaptercreatesgraph_node/graph_edgewith their key columnsCOLLATE "C"and without the redundant source-side covering index. Both apply to new tables only —CREATE TABLE IF NOT EXISTSnever rewrites one that exists — so a store created by an older build keeps the locale collation and the extra index, and keeps working. A migration additionally sets per-table autovacuum scale factors (vacuum 0.05,insert 0.05,analyze 0.02) on both tables; it touches no server setting.PgGraphAdapterrequires PostgreSQL 13 or newer, because that migration setsautovacuum_vacuum_insert_scale_factor(added in PostgreSQL 13); on 12 the migration fails and the adapter refuses to initialise. The vector adapter and the relational store have no such requirement. Both graph-adapter constructors run withplan_cache_mode = force_custom_plan:PgGraphAdapter::newsets it as a connection option on the pool it opens, andfrom_connection(used by the shared-Postgres layout, where the pool belongs to the caller) sends it as aSET LOCALwith each parameterised statement, in a transaction so it cannot leak to the next borrower of that connection. - Not in OSS. Embedded Qdrant and on-device LiteRT inference (Android) are
not part of the
cognee-rsrepository. - Full Postgres stack (relational + graph + vector on one Postgres) is the one remaining adapter milestone — see roadmap/.
MockEmbeddingEngine, MockGraphDB, MockVectorDB, and MockStorage (the
testing feature) back the test suite — see
test patterns.