Hybrid keyword + vector search that runs over readable projections โ not 3M tokens of raw FHIR JSON. Vectors live beside the data, ABAC is enforced at retrieval, and every hit cites its source record.
"Find when this kid's anxiety started spiking around school" is a clinical question, not a FHIR query. bonfireDB embeds your clean operational views โ notes, assessments, timelines โ and runs hybrid search over them. Keyword recall catches the codes and exact phrases; vector recall catches the way a clinician actually wrote it.
Keyword + vector together. Exact-match precision where it matters, semantic recall where the wording varies.
Search reads the same readable projections your app does โ never raw Bundle JSON the agents can't parse.
Permissions enforced per-hit at query time. Filtering happens before results leave the database, never in the prompt.
Every result points back to the record it came from. No floating snippets, no "trust me" answers.
bonfireDB stores embeddings in pgvector inside the same Postgres that holds the source of truth. No second vector store to sync, no copy of PHI shipped to a third-party index, no drift between "what's in the DB" and "what's searchable."
pgvector + Postgres + Bedrock-in-VPC. Nothing new to operate.
const hits = await clinical.search.hybrid({ patientId, query: "worsening anxiety around school stress", citations: true }) // hits are ABAC-scoped to this caller, // ranked by keyword + vector relevance, // each carrying a citation to its source record hits.map(h => ({ view: h.source.view, // notesByPatient | timeline | ... score: h.score, cite: h.source.recordId, // the record this came from snippet: h.snippet }))
Putting "only show records this clinician can see" in the system prompt is a hope, not a control. bonfireDB applies ABAC at retrieval โ the search itself never returns a row the caller isn't entitled to. The model only ever sees what it's already allowed to see.
Index returns everything, the prompt is told to "be careful," and one jailbreak or a sloppy chain leaks another patient's record into the context window.
Every hit is patient- and tenant-scoped before it leaves Postgres. The unauthorized row is never embedded into the prompt in the first place.
Credit where it's due: Google Agent Search for healthcare already ships FHIR-native semantic search today, and it's a serious managed offering. The catch is that Google has announced its end of life for 2027-05-15 โ so building your retrieval layer on it means building on a clock. bonfireDB makes a different bet: keep semantic search in the same Postgres you already run, so retrieval isn't a separate managed service that can be deprecated out from under you.
FHIR-native semantic search, managed by Google โ genuinely the closest shipping competitor. Announced end of life 2027-05-15. Re-verify the date and migration path against Google's current docs before you commit.
pgvector colocated with your source of truth, ABAC at retrieval, cited hits, embeddings under your own BAA. Pre-launch and early-access โ fewer batteries included than a hyperscaler service, by design: one boundary, nothing extra to operate.
Semantic search is a sidecar projection fed from the store โ not a blocking step on your writes. When you save a note, the operational read models are fresh on commit; the embedding job runs on the async index lane and reports its own status. No write is held hostage to an embedding call.
clinical.notes.create(...) returns immediately. Operational views are fresh on commit.
The async index lane embeds the new content into pgvector beside the data โ heavy work, off the write path.
The write's freshness object marks indexes.semanticSearch as pending โ fresh, so you always know what's searchable.
No guessing whether the index caught up. The freshness lifecycle distinguishes what's committed and queryable now from what's still being indexed.
{
status: "committed",
views: {
notesByPatient: "fresh",
timeline: "fresh"
},
indexes: {
semanticSearch: "pending",
agentContext: "pending"
}
}
Hybrid search isn't a separate stack from your AI layer โ it's the retrieval primitive underneath it. Agents read these same cited, permission-aware projections, never raw FHIR by default.
Expose hybrid search as a scoped, cited MCP tool โ safe by default.
Custom MCP builder โNotes, assessments, observations โ the typed views search reads from.
App-native primitives โThe freshness lifecycle that tells you what's indexed and what's pending.
Always fresh โThe ABAC engine enforced at retrieval, every read audited.
Clinical authorization โSemantic search over clean clinical views, ABAC at retrieval, citations baked in โ without standing up a second vector store. Start building on the open-source core.
No. bonfireDB stores embeddings in pgvector inside the same Postgres that holds your source of truth, so there's no second vector store to sync, no copy of PHI shipped to a third-party index, and no drift between what's in the DB and what's searchable. It's designed so filtering, scoping, and similarity all happen in one query.
ABAC is applied at retrieval, not in the prompt. Every hit is patient- and tenant-scoped before it leaves Postgres, so an unauthorized row is never embedded into the model's context in the first place. The model only ever sees what the caller is already allowed to see.
Both. bonfireDB runs hybrid search โ keyword recall catches exact codes and phrases, while vector recall catches the way a clinician actually wrote it. Results are ranked by combined keyword + vector relevance, and every hit cites the source record it came from.
No. Search reads the same clean, readable projections your app does โ notes, assessments, timelines โ never raw FHIR Bundle JSON that agents can't parse. FHIRยฎ is a registered trademark of HL7, used descriptively here.
Semantic search is a sidecar projection fed by an async index lane, so no write is blocked on an embedding call. Operational views are fresh on commit, and each write's freshness object marks the semantic index as pending until it's embedded โ so you always know what's searchable, with no silent rot.