How do you generate realistic clinical seed data for a healthcare app?

Run bonfire seed --patients 50 --profile us-core. It generates clinically coherent, longitudinal, comorbidity-correlated, profile-valid patients — HbA1c trends, medication escalation, imaging plus narrative notes — straight into your local Postgres-first instance, wired to the typed SDK. Your first realistic Patient is five minutes away, not a sprint.

the onboarding wedge

Why does your healthcare app pass the sandbox and crash on the first real patient?

Because the data you tested on was nothing like a real chart. Open Epic gives you eight patients with sparse data. Synthea produces single-condition patients with no clinical depth. Your app demos green, then the first real patient arrives with three comorbidities, a four-year HbA1c trend, escalating insulin, an imaging report, and a wall of narrative notes — and the code that "worked" falls over. The fix is seed data that looks like the chart your app will actually meet on day one.

Clinically coherent

A patient with type 2 diabetes carries the labs, meds, and notes that diabetes actually drags along — not a random scatter of unrelated codes.

Longitudinal

Values move over time. An HbA1c reads as a trend across visits, with medication escalation that tracks the trajectory — not a single static row.

Comorbidity-correlated

Conditions cluster the way real ones do. Diabetes pulls in hypertension and hyperlipidemia; the chart hangs together instead of contradicting itself.

Profile-valid

--profile us-core means every generated resource validates against US Core — so your app is tested against the shapes it must ship.

Your first realistic Patient, in five minutes

One command stands up a roster of dense, coherent charts inside your local Postgres-first instance and wires them to the typed SDK. No external fetch, no fixture-by-hand, no "I'll add real data later" that never happens. You read the seeded patients through the exact same client your app uses in production.

Generates into your local instance — Postgres + pgvector, no Redis, no cloud round-trip to start.
Seeded resources are immediately queryable through the typed SDK — the same client your app reads with.
Deterministic with a seed value, so the same command reproduces the same roster across machines and CI.

bonfire seed — dense charts on the first run, not the fortieth.

terminal
# 50 dense, US-Core-valid patients into local Postgres
$ bonfire seed --patients 50 --profile us-core

 50 patients generated (deterministic, seed=42)
 1,284 Observations  // HbA1c trends, vitals, lipids
 612 MedicationRequests  // escalation over time
 188 DiagnosticReports + DocumentReferences
 all resources US-Core valid · queryable via SDK

# read them back through the typed client
$ bonfire query "Patient?_count=50"
what "dense" actually means

What does a clinically-dense seed patient contain?

A dense patient is one whose chart tells a story that holds together over time. A seeded diabetic doesn't get a lone diagnosis code — they get the trend, the treatment response, and the narrative a clinician would expect to read. Store a SOAP note as a FHIR DocumentReference, a lab as an Observation, a prescription as a MedicationRequest — and bonfire generates them correlated, not in isolation.

Sparse fixtures (Synthea / sandbox)

  • One condition, a handful of codes, no temporal arc
  • Single static lab value — no trend to chart or to break your math on
  • Meds unrelated to the diagnosis; no escalation, no response
  • No narrative notes — nothing for an AI scribe or summarizer to read
  • Passes the demo, crashes on the first real patient

A bonfire-seeded patient

  • Comorbidities that cluster realistically (diabetes + HTN + hyperlipidemia)
  • HbA1c read as a four-year trend across dated encounters
  • Medication escalation that tracks the lab trajectory over time
  • Imaging (DiagnosticReport) plus narrative DocumentReference notes
  • Every resource US-Core valid — the shape your app must ship against

Honest framing: bonfireDB is pre-launch / early access. This page describes the seed generator's design, not a benchmark. Synthea is excellent for population-scale synthetic data; bonfire's seed is tuned for a different job — a handful of deep charts that stress an outpatient app's real read paths in minutes.

Per-test snapshot and reset

Seed once, then snapshot the database and reset between tests in milliseconds. Every test starts from the same dense roster, mutates freely, and rolls back — so your integration suite runs against realistic charts without leaking state from one test into the next.

  • Snapshot captures the full seeded state; reset restores it without re-running generation.
  • Each test gets an isolated, identical starting chart — no order-dependent flake.
  • Fast enough to reset in a beforeEach, so suites stay both realistic and clean.

Realistic data and clean isolation are usually a tradeoff. Snapshot/reset gives you both.

patient.test.ts
import { seed, snapshot } from "bonfire-db/test"
import { clinical } from "../client"

// seed 50 dense charts once, snapshot the state
const snap = await snapshot(
  await seed({ patients: 50, profile: "us-core" })
)

beforeEach(async () => {
  await snap.reset()   // back to the dense roster, ms
})

test("summarizes a multi-year HbA1c trend", async () => {
  const obs = await clinical.observations.list({
    patient: "pt-001", code: "4548-4"   // HbA1c
  })
  expect(obs.length).toBeGreaterThan(4)  // a real trend
})
from zero to a dense chart

Three steps to a realistic Patient

1

Create the project

One command scaffolds the Postgres-first instance, pgvector, and the typed SDK — no Redis to provision. (CLI in early access.)

2

Seed dense charts

Generate 50 longitudinal, comorbidity-correlated, US-Core-valid patients straight into local Postgres.

bonfire seed --patients 50 --profile us-core
3

Snapshot & build

Snapshot the roster, reset between tests, and read it all through the same typed client your app ships with.

await snap.reset()
side by side

Seed data options for a clinical app, compared

CapabilityOpen Epic sandboxSyntheabonfire seed
Patients available~8, fixedPopulation-scale--patients N, your call
Clinical depth per chartSparseOften single-conditionDense, multi-condition
Longitudinal trends (e.g. HbA1c)MinimalPartialBuilt in, dated
Comorbidity correlationNoLimitedCorrelated by design
Narrative notes for AI to readRareNoDocumentReference notes
Profile validity (US Core)VariesVaries by config--profile us-core
Wired to your typed SDKExternal APIFiles to importInto local Postgres, queryable
Per-test snapshot / resetNoNoBuilt in, ms

bonfireDB is early-stage; this comparison describes product design and positioning, not a benchmark. Synthea (MITRE) is a strong open-source synthetic-data engine for population studies — a different job than a handful of deep charts for app testing. "FHIR" and "US Core" are descriptive references to HL7®'s standards; verify current implementation-guide versions before you ship.

where this fits

Dense seed data is the on-ramp to the rest of the backend

AI scribe Fire Starter

Seed dense charts with narrative notes, then build the transcript-to-signed-note lifecycle on top of real-looking data.

Explore →

How it works

TypeScript + Postgres + pgvector, FHIR R4 underneath, no Redis — see how seed, SDK, and store fit together.

Explore →

Terminology & validation

Seeded codes are real codes — validated against LOINC, SNOMED CT, RxNorm, and ICD-10 on write.

Explore →

FHIR underneath

Every seeded patient is a clean FHIR R4 resource — export the roster the moment you need to.

Explore →

You build the app. Bonfire is the clinical data layer underneath.

Generate 50 clinically-dense, longitudinal, US-Core-valid patients into local Postgres in five minutes — then snapshot and reset between tests. Start building on the open-source core.

FAQ

Frequently asked questions

How do I generate synthetic FHIR patients for local development?

Run bonfire seed --patients 50 --profile us-core. It is designed to generate longitudinal, comorbidity-correlated, US-Core-valid patients straight into your local Postgres instance, immediately queryable through the typed SDK. bonfireDB is in early access, so this describes the seed generator's design.

What is the difference between bonfire seed and Synthea for clinical seed data?

As of 2026 (verify current), Synthea (MITRE) is an excellent population-scale synthetic-data engine, often producing single-condition patients. bonfire's seed is tuned for a different job: a handful of deep, multi-condition charts with longitudinal trends and narrative notes to stress an outpatient app's real read paths in minutes.

How do I seed a local Postgres database with realistic clinical data?

One command generates dense charts into your local Postgres-first instance (Postgres + pgvector, no Redis, no cloud round-trip). Seeding is designed to be deterministic with a seed value, so the same command reproduces the same roster across machines and CI.

Does the seed data include longitudinal trends and narrative notes?

Yes, by design. A seeded diabetic patient is meant to carry an HbA1c trend across dated encounters, medication escalation that tracks that trajectory, imaging as a DiagnosticReport, and narrative notes as DocumentReferences for an AI scribe or summarizer to read.

How do I reset clinical test data between integration tests?

bonfire is designed to let you seed once, snapshot the full database state, then reset between tests in milliseconds. Each test starts from the same dense roster, mutates freely, and rolls back, so suites stay realistic and isolated without re-running generation.