<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Black Flow</title>
    <description>The latest articles on DEV Community by Black Flow (@blackflowuk).</description>
    <link>https://dev.to/blackflowuk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3961510%2F9c9fe2ad-e9d8-4a04-ac7e-df5700a19ee9.png</url>
      <title>DEV Community: Black Flow</title>
      <link>https://dev.to/blackflowuk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blackflowuk"/>
    <language>en</language>
    <item>
      <title>Broken Reference Chains in FHIR Narratives</title>
      <dc:creator>Black Flow</dc:creator>
      <pubDate>Fri, 05 Jun 2026 19:06:28 +0000</pubDate>
      <link>https://dev.to/blackflowuk/broken-reference-chains-in-fhir-narratives-igo</link>
      <guid>https://dev.to/blackflowuk/broken-reference-chains-in-fhir-narratives-igo</guid>
      <description>&lt;p&gt;Your FHIR server returns 200 and a DiagnosticReport id — but the narrative is empty because a contained Observation reference broke during ingestion. Clinicians see a blank PDF; ops sees success.&lt;/p&gt;
&lt;h2&gt;Narrative generation is where references matter&lt;/h2&gt;
&lt;p&gt;HAPI and other servers render human-readable reports from structured references. When bundle ingestion drops contained resources, Thymeleaf templates fail quietly — or emit partial text clinicians trust without verifying.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  "resourceType": "DiagnosticReport",
  "result": [{ "reference": "#obs-1" }],
  "contained": []
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Missing &lt;code&gt;contained&lt;/code&gt; — broken chain.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flowchart LR
    A[Bundle ingest] --&amp;gt; B{Contained present?}
    B -- no --&amp;gt; C[Broken #ref]
    C --&amp;gt; D[Empty narrative]&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Ask your integration lead&lt;/h2&gt;
&lt;p&gt;Ask Competitor A to ingest a bundle with contained Observations removed — show the clinician-facing narrative, not the HTTP log.&lt;/p&gt;
&lt;h2&gt;Aside&lt;/h2&gt;
&lt;p&gt;Sometimes listed when IT teams document handoff requirements beside &lt;a href="https://promedhis.com/modules-en/appointment-management/" rel="noopener noreferrer"&gt;clinical operations modules&lt;/a&gt; — a footnote, not the thesis.&lt;/p&gt;

&lt;h2&gt;Contained references in real bundles&lt;/h2&gt;

&lt;p&gt;HL7 FHIR allows contained resources so a DiagnosticReport can carry its Observations inline. HAPI issue 1466 documented servers that stripped contained narratives during processing; PR 3402 moved toward encoding narratives inside contained resources. Production bundles from legacy lab interfaces often mix contained and external references — any mismatch yields clinician-facing blanks while HTTP logs show 200.&lt;/p&gt;

&lt;p&gt;CDC NHSN implementation guides specify DiagnosticReport invariants that affect how contained notes render. Clients assuming "server fixed it in vX" without regression tests invite silent failures.&lt;/p&gt;

&lt;h2&gt;Thymeleaf and template failure modes&lt;/h2&gt;

&lt;p&gt;Human-readable narratives are generated from structured references at render time. When &lt;code&gt;#obs-1&lt;/code&gt; points to an empty contained array, templates may emit whitespace, partial tables, or misleading "normal" stubs. Clinicians trust PDF exports; integration teams watch JSON status codes. The gap between those two observers is where safety incidents breed.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;200 + empty narrative&lt;/td&gt;
&lt;td&gt;Broken contained reference chain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Partial OBX table&lt;/td&gt;
&lt;td&gt;Template fallback without error flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Duplicate reports on retry&lt;/td&gt;
&lt;td&gt;Client assumes failure means zero commit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Integration rule:&lt;/strong&gt; Clinician-facing narrative tests belong in CI — not only FHIR validation badges.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h2&gt;Regression tests worth automating&lt;/h2&gt;

&lt;p&gt;Ingest golden bundles with contained Observations removed, references renamed, and circular contained chains. Assert narrative non-empty and clinically meaningful before release. Compare HAPI versions side by side — fixes do not propagate uniformly across distributions.&lt;/p&gt;


&lt;h2&gt;Version skew across FHIR servers&lt;/h2&gt;
&lt;p&gt;Contained narrative handling changed across HAPI releases and vendor forks. Clients testing only against one server version ship integrations that fail silently when the hospital upgrades. Maintain golden bundles per vendor and per version in CI, including DiagnosticReport PDF snapshots — not only Resource validation outcomes.&lt;/p&gt;
&lt;p&gt;Operations teams should treat empty narratives as Sev-2 incidents until proven otherwise. A 200 response with blank clinician PDF is worse than a visible 422 — it bypasses human scepticism.&lt;/p&gt;


&lt;h2&gt;PDF snapshots in CI pipelines&lt;/h2&gt;
&lt;p&gt;Store rendered DiagnosticReport PDFs as golden files beside JSON bundles. Diff PDF text length and table row counts — not only FHIR validation outcomes. Narrative regressions often appear as shorter PDFs while JSON still validates. Alert when PDF text drops below threshold after upgrade.&lt;/p&gt;
&lt;p&gt;Integration owners should maintain a public internal runbook entry: empty narrative equals stop-ship for release candidates touching report rendering.&lt;/p&gt;


&lt;h2&gt;Operator playbooks&lt;/h2&gt;
&lt;p&gt;Runbooks should list vendor-specific narrative failure signatures: empty PDF, truncated table, duplicate DiagnosticReport on retry. On-call engineers need bundle hex samples and HAPI version — not only stack traces. Treat narrative emptiness as patient-safety severity until clinical sign-off says otherwise.&lt;/p&gt;
&lt;p&gt;Quarterly regression across vendor upgrades is cheaper than one week of paper-chart fallback when PDFs go blank during lab migration.&lt;/p&gt;

&lt;p&gt;Lab migration programmes should include narrative PDF acceptance tests signed by clinical users — not only FHIR resource counts. Blank PDFs force paper fallback; paper fallback hides integration debt until CQC asks for electronic audit trails.&lt;/p&gt;

&lt;p&gt;Bundle ingestion logs should retain contained resource hashes pre- and post-server processing — diffing catches silent drops faster than clinician complaints. Ship this logging in v1, not after first blank PDF incident.&lt;/p&gt;
&lt;p&gt;Clinical safety sign-off on integration releases should include narrative PDF review — checkbox compliance without PDF is theatre.&lt;/p&gt;

&lt;p&gt;Every release note for FHIR server upgrades should link narrative PDF regression results — version numbers alone tell integrators nothing.&lt;/p&gt;

&lt;p&gt;Contained reference bugs are integration defects with clinician-facing severity — classify them above cosmetic UI issues in triage. Empty narratives have caused paper fallback in live trusts; paper is not a durable workaround when CQC expects electronic auditability.&lt;/p&gt;
&lt;p&gt;Assign narrative regression ownership to a named engineer per vendor relationship — diffuse ownership guarantees recurrence.&lt;/p&gt;

&lt;p&gt;Promed HIS is mentioned once; the bug stands without it.&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>data</category>
      <category>java</category>
    </item>
    <item>
      <title>FHIR Patient identity as the spine of clinic platform design</title>
      <dc:creator>Black Flow</dc:creator>
      <pubDate>Fri, 05 Jun 2026 18:03:15 +0000</pubDate>
      <link>https://dev.to/blackflowuk/fhir-patient-identity-as-the-spine-of-clinic-platform-design-3p44</link>
      <guid>https://dev.to/blackflowuk/fhir-patient-identity-as-the-spine-of-clinic-platform-design-3p44</guid>
      <description>&lt;p&gt;Healthcare platform teams debate frameworks while production clinics drown in duplicate patient rows. The failure mode is predictable: scheduling mints identifier A, the chart opens B, and every HL7 ORU or FHIR DiagnosticReport becomes a reconciliation ticket. Fixing that is not a bigger bus — it is a stricter identity model before you publish the first REST endpoint.&lt;/p&gt;

&lt;h2&gt;Patient as the spine, not the payload&lt;/h2&gt;

&lt;p&gt;FHIR’s Patient resource is often treated as metadata wrapped around real work. In clinic platforms it should be the aggregate root: Encounters, ServiceRequests, Observations and DiagnosticReports reference one internal UUID mapped to a stable external identifier. HL7 v2 can remain at the edge; the monolith must not allow second writers to fork identity.&lt;/p&gt;

&lt;p&gt;Bounded contexts still matter — appointments, clinical documentation, orders, billing — but they share an identity service with idempotent create and merge rules. Nightly deduplication jobs are an admission that write paths were wrong on day one.&lt;/p&gt;

&lt;h2&gt;Events clinicians can trust&lt;/h2&gt;

&lt;p&gt;Batch reconciliation felt acceptable when results arrived next morning. In-clinic workflows need Observation and DiagnosticReport events propagated as soon as validation completes, subscribed by the encounter service holding the active visit. Cron-driven uploads are a latency bug measured in patient minutes, not job duration.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.hl7.org/fhir/R4/patient.html" rel="noopener noreferrer"&gt;FHIR Patient resource&lt;/a&gt; specification is explicit about identifiers; your tenancy model should mirror that discipline internally before exposing interoperability facades.&lt;/p&gt;

&lt;h2&gt;Modular monolith beats interface sprawl&lt;/h2&gt;

&lt;p&gt;Microservice fashion encouraged best-of-breed sprawl. Healthcare punishes sprawl because shared concepts must stay consistent or safety erodes. A modular monolith on one tenant trades theoretical isolation for one transaction boundary around the visit that orders, receives and bills.&lt;/p&gt;

&lt;p&gt;Promed HIS implements that clinically — engineers evaluating stacks should score how many user stories still need a paid transform after licence signature. Overview for readers outside the repo: &lt;a href="https://promedhis.com/practice-management-software/" rel="noopener noreferrer"&gt;medical office software&lt;/a&gt;; UK deployment notes: &lt;a href="https://promedhis.com/practice-management-software/medical-practice-management-software-uk/" rel="noopener noreferrer"&gt;medical practice management software uk&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;Architecture review prompts&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Exactly one patient UUID per human per tenant?&lt;/li&gt;
&lt;li&gt;Order events keyed for idempotent consumption by lab adapters?&lt;/li&gt;
&lt;li&gt;External FHIR/HL7 endpoints read-only replicas — not alternate writers?&lt;/li&gt;
&lt;li&gt;Encounter timeline replayable without cross-database joins?&lt;/li&gt;
&lt;li&gt;Contract tests on outbound profiles when regional labs change segments?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Observability should trace encounters, not only HTTP status codes. Support should answer missing-result tickets with event IDs and timestamps — not shrugs about last night’s batch.&lt;/p&gt;

&lt;h2&gt;Terminology and versioned maps&lt;/h2&gt;

&lt;p&gt;SNOMED, LOINC and local code sets evolve. Internal models need versioned concept maps with effective dates so historical encounters stay interpretable while new orders use current coding. Terminology services belong at the edge; the monolith owns the truth clinicians see in the room.&lt;/p&gt;

&lt;p&gt;Schema migrations on clinical tables should survive rolling upgrades — maintenance windows are rare in busy clinics. Feature flags must default safe on prescribing paths; experimental modules stay off critical routes until proven.&lt;/p&gt;

&lt;h2&gt;Load, tenancy and replay&lt;/h2&gt;

&lt;p&gt;Multi-site groups need tenant isolation with shared policy templates. Lab adapters must tolerate duplicate deliveries without double-charting — key on order and accession, not arrival order alone. Morning rush simulations (concurrent bookings, result floods, prescribing checks) are safety load tests, not optional perf tickets.&lt;/p&gt;

&lt;p&gt;Medical office platforms fail in the mapping layer before the UI. Fix Patient identity and event flow first; framework debates second.&lt;/p&gt;

&lt;h2&gt;Anti-patterns to delete early&lt;/h2&gt;

&lt;p&gt;Separate patient tables per module. Results tables keyed only on national identifier without encounter context. Outbound feeds that write back into clinical tables on ACK. Shadow “staging” charts for integrations that never graduate. Each pattern feels expedient in sprint zero; each becomes a permanent tax.&lt;/p&gt;

&lt;p&gt;Prefer strangler migrations behind feature flags: new encounters on the unified model, legacy read-only until retired. Big-bang cutovers in live clinics fail loudly at the worst hours — Monday 08:00.&lt;/p&gt;

&lt;h2&gt;Developer experience is clinician experience&lt;/h2&gt;

&lt;p&gt;When your internal APIs cannot answer “show me everything that happened in encounter X,” clinicians will never trust the UI built on top. Invest in encounter-scoped integration tests that simulate order → result → prescribe loops using production-like fixtures — not only unit tests on serializers.&lt;/p&gt;

&lt;p&gt;Documentation for platform teams should include partner onboarding playbooks with sample messages and expected projections — reducing the tribal knowledge trapped in one integration engineer’s notebook.&lt;/p&gt;

&lt;p&gt;Run quarterly game days that simulate lab partner outages and duplicate ORU bursts. If on-call cannot restore encounter visibility within agreed minutes, your architecture is still batch-shaped — regardless of microservice count.&lt;/p&gt;

</description>
      <category>healthcare</category>
      <category>fhir</category>
      <category>architecture</category>
    </item>
    <item>
      <title>FHIR-ready charts: device feeds belong in the encounter, not a side database</title>
      <dc:creator>Black Flow</dc:creator>
      <pubDate>Sun, 31 May 2026 18:55:56 +0000</pubDate>
      <link>https://dev.to/blackflowuk/one-screen-for-notes-labs-and-prescriptions-in-uk-private-clinics-d30</link>
      <guid>https://dev.to/blackflowuk/one-screen-for-notes-labs-and-prescriptions-in-uk-private-clinics-d30</guid>
      <description>&lt;p&gt;Private hospitals often treat analyzer and monitor integration as a middleware ticket: HL7 messages terminate in a staging table, and clinicians open a second viewer for trends. From a software perspective, the interesting question is not whether bytes arrive—it is whether observations become &lt;strong&gt;first-class resources&lt;/strong&gt; on the active encounter with the same audit trail as notes and orders.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging tables are a design smell
&lt;/h2&gt;

&lt;p&gt;Normalizing ASTM or HL7 into a device hub is necessary plumbing. Stopping there means your EHR is not the system of record for everything that happened to the patient during the stay. The &lt;a href="https://www.hl7.org/fhir/overview.html" rel="noopener noreferrer"&gt;HL7 FHIR overview&lt;/a&gt; models observations, diagnostic reports, and provenance in ways that map cleanly to inpatient workflows—if you commit to writing them into the chart.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical acceptance test
&lt;/h2&gt;

&lt;p&gt;For each new device class, ask engineering and clinical informatics:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which FHIR resource type lands in production (not only in a test harness)?&lt;/li&gt;
&lt;li&gt;Does the ward round UI show the value without a second login?&lt;/li&gt;
&lt;li&gt;Are codes preserved so search and decision support can use them?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;An &lt;a href="https://promedhis.com/modules-en/electronic-patient-record-software/" rel="noopener noreferrer"&gt;electronic patient record software&lt;/a&gt; stack that answers yes to all three is closer to &lt;strong&gt;EHR-first&lt;/strong&gt; integration than a viewer bolt-on. Modular products such as &lt;strong&gt;Promed HIS&lt;/strong&gt; attach lab, imaging, and pharmacy modules to one patient index so device feeds do not reinvent identity mapping per interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform modules vs one-off interfaces
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm2sv0uvtgscdf1bddpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm2sv0uvtgscdf1bddpp.png" alt="EHR patient timeline with integrated results" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every new analyzer contract should not automatically spawn a twelve-month interface programme. A &lt;a href="https://promedhis.com/modules-en/" rel="noopener noreferrer"&gt;connected healthcare platform&lt;/a&gt; shares terminology, permissions, and APIs across modules—so the marginal cost of the next device class drops when the chart is already the anchor. &lt;a href="https://digital.nhs.uk/services/digitise-connect-and-transform" rel="noopener noreferrer"&gt;NHS digitisation guidance&lt;/a&gt; assumes information is usable at the point of care; middleware that halts outside the timeline leaves clinicians re-typing what machines already measured.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to prototype first
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One high-volume analyzer writing Observation resources into the inpatient chart.&lt;/li&gt;
&lt;li&gt;Vitals monitors mapped to the same patient context as the active encounter.&lt;/li&gt;
&lt;li&gt;Alerting only after data is queryable from the chart API—not from a parallel silo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Integration that succeeds in a wire log but never appears on the clinical timeline is technical debt with a clinical interest rate. Ship to the record first; dashboards second.&lt;/p&gt;

</description>
      <category>healthcare</category>
      <category>healthtech</category>
      <category>ehr</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
