PostgreSQL + pgvector for data, Redis + BullMQ for jobs, PHI vault for medical data
The storage layer underpins everything. Three distinct systems handle different kinds of data:
iv_postgres, database irievybz_core, user irievybziv_redis/opt/irievybz/data/oshun-phi/photos on the Hetzner VPS. Hetzner GDPR-compliant hosting. AWS migration path is documented but not yet scheduled.The database layer supports all 10 patient and operational journeys:
src/db.js — PostgreSQL connection pool. All modules import from here — never create a separate pool.src/memory.js — Knowledge storage and retrieval. Key exports: storeConversation() (line 177), storeKnowledge() (line 195), storeProfile() (line 213), hybridSearch() (line 125), searchVector() (line 28), searchKeyword() (line 83).src/core_memory.js — Persistent per-tenant core memory (persona, goals, business context). Key exports: getCoreMemory(), upsertSection().src/consolidator_memory.js — Per-turn memory consolidation and daily digests. Key exports: consolidateTurn() (line 38), runDailyDigest().src/contacts.js — Contact CRUD with auto-merge across channels. Key exports: findOrCreateContact() (line 6), mergeContacts() (line 202), acquireContactLock() (line 128).src/scheduler.js — BullMQ job scheduling for follow-ups and timed sequences.antigravity-core/schema.sql — Full database schema definition.antigravity-core/migrations/ — 33 numbered migration files. All are idempotent (IF NOT EXISTS). Run manually via psql — never auto-applied.Karen uses a hybrid search approach to retrieve relevant memory. All four methods are combined via Reciprocal Rank Fusion (RRF) to produce a single ranked result set:
searchVector() — pgvector semantic similarity. Converts the query to an embedding and finds the nearest stored vectors. Best for meaning-based retrieval ("what did this patient ask about last time").searchKeyword() — PostgreSQL full-text search (tsvector/tsquery). Best for exact term matching ("Botox", procedure names, contact names).searchTags() — Tag-based filtering. Memories can be tagged by category (e.g. care_plan, booking, complaint) for fast scoped retrieval.searchExact() — Exact string match against indexed fields. Used for lookups by ID, phone number, or known unique values.The combined hybridSearch() function (line 125 of src/memory.js) runs all four in parallel and merges the ranked results before returning to the context builder.
src/core_memory.js related to owner_tenant_id. This affects how per-tenant core memory (persona, goals) is read back. Do not rely on getCoreMemory() returning the correct owner context until this is patched.