<?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: Om Jariwala</title>
    <description>The latest articles on DEV Community by Om Jariwala (@omjariwala).</description>
    <link>https://dev.to/omjariwala</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4154665%2F7f287aa5-0d95-410d-ae37-0b929feb7bbf.jpg</url>
      <title>DEV Community: Om Jariwala</title>
      <link>https://dev.to/omjariwala</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omjariwala"/>
    <language>en</language>
    <item>
      <title>Why Traditional Webhooks Break Under RPM Load</title>
      <dc:creator>Om Jariwala</dc:creator>
      <pubDate>Fri, 02 Oct 2026 05:32:03 +0000</pubDate>
      <link>https://dev.to/omjariwala/why-traditional-webhooks-break-under-rpm-load-470l</link>
      <guid>https://dev.to/omjariwala/why-traditional-webhooks-break-under-rpm-load-470l</guid>
      <description>&lt;p&gt;A webhook works fine when your system is small.&lt;/p&gt;

&lt;p&gt;But when you start handling &lt;strong&gt;FHIR data, RPM devices, patient observations, alerts, and hundreds of events&lt;/strong&gt;, the simple:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Device → Webhook → API → Database&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;model can become a problem.&lt;/p&gt;

&lt;p&gt;The issue isn't the webhook itself.&lt;/p&gt;

&lt;p&gt;It's making the webhook responsible for everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RPM Device
    ↓
Webhook
    ↓
Validate
    ↓
Transform to FHIR
    ↓
Save Data
    ↓
Run Clinical Rules
    ↓
Send Alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine hundreds of devices doing this at the same time.&lt;/p&gt;

&lt;p&gt;One slow dependency can hold up the entire request.&lt;/p&gt;

&lt;h2&gt;
  
  
  A better approach
&lt;/h2&gt;

&lt;p&gt;Use the webhook for ingestion and move the heavy work into an event-driven pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RPM Device
    ↓
API / Webhook
    ↓
Message Queue
    ↓
Workers
    ↓
FHIR Processing
    ↓
Clinical Rules
    ↓
FHIR Server / Database
    ↓
Notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The queue gives your system somewhere to hold events when traffic spikes or a downstream service is temporarily unavailable.&lt;/p&gt;

&lt;p&gt;It also makes retries much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't forget duplicate events
&lt;/h2&gt;

&lt;p&gt;Distributed systems can deliver the same event more than once.&lt;/p&gt;

&lt;p&gt;So your pipeline should be idempotent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Receive Event
      ↓
Check Event ID
      ↓
Already Processed?
   ↙          ↘
 Yes           No
 ↓             ↓
Ignore       Process
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Processing an event twice should not create incorrect clinical data.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What about FHIR?
&lt;/h2&gt;

&lt;p&gt;An RPM reading might become a FHIR &lt;code&gt;Observation&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"resourceType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Observation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"final"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"coding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://loinc.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"8480-6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Systolic blood pressure"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"valueQuantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mmHg"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But creating the FHIR resource is only one part.&lt;/p&gt;

&lt;p&gt;You still need to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Patient and device identity&lt;/li&gt;
&lt;li&gt;Duplicate events&lt;/li&gt;
&lt;li&gt;Out-of-order events&lt;/li&gt;
&lt;li&gt;Retries&lt;/li&gt;
&lt;li&gt;Validation&lt;/li&gt;
&lt;li&gt;Clinical rules&lt;/li&gt;
&lt;li&gt;Auditability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The real question
&lt;/h2&gt;

&lt;p&gt;Don't ask only:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Does my webhook work?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“What happens when 10x the events arrive, the FHIR server goes down, or the same event arrives twice?”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where architecture starts to matter.&lt;/p&gt;

&lt;p&gt;A webhook should tell your system:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Something happened.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It shouldn't necessarily be responsible for everything that happens next.&lt;/p&gt;

&lt;p&gt;For RPM and FHIR systems, separating &lt;strong&gt;ingestion from processing&lt;/strong&gt; gives you a much stronger foundation for scaling and reliability.&lt;/p&gt;

</description>
      <category>healthcare</category>
      <category>fhirhealthcare</category>
      <category>programming</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
