<?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: Dhruv Jain</title>
    <description>The latest articles on DEV Community by Dhruv Jain (@dhruv_jain_8b924cc8f63fb8).</description>
    <link>https://dev.to/dhruv_jain_8b924cc8f63fb8</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%2F4007356%2Ff82b93be-540e-42fe-9d5a-bffa808cc6a9.jpg</url>
      <title>DEV Community: Dhruv Jain</title>
      <link>https://dev.to/dhruv_jain_8b924cc8f63fb8</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhruv_jain_8b924cc8f63fb8"/>
    <language>en</language>
    <item>
      <title>Two-stage AI triage: Claude on Bedrock plus a conformal ML ensemble, on DynamoDB and Vercel</title>
      <dc:creator>Dhruv Jain</dc:creator>
      <pubDate>Mon, 29 Jun 2026 06:02:05 +0000</pubDate>
      <link>https://dev.to/dhruv_jain_8b924cc8f63fb8/two-stage-ai-triage-claude-on-bedrock-plus-a-conformal-ml-ensemble-on-dynamodb-and-vercel-50a</link>
      <guid>https://dev.to/dhruv_jain_8b924cc8f63fb8/two-stage-ai-triage-claude-on-bedrock-plus-a-conformal-ml-ensemble-on-dynamodb-and-vercel-50a</guid>
      <description>&lt;p&gt;Solace assigns an emergency-department acuity level (ESI) from a patient's own words and then refines it at the bedside. I wanted a model that helps a clinician without ever pretending to make the call. Here is how the triage brain works, and how it sits on DynamoDB and Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage one: narrative ESI on intake
&lt;/h2&gt;

&lt;p&gt;A patient describes what is wrong by voice or text, in any of 20+ languages (speech runs through Amazon Transcribe and Polly). Amazon Bedrock (Claude) reads that narrative and produces a provisional ESI before any vitals exist. This is what powers the calm spoken result the patient hears and the first sort of the live clinician queue.&lt;/p&gt;

&lt;p&gt;Everything runs inside AWS managed services covered by the Business Associate Agreement, so patient text never leaves the BAA boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage two: refinement at the bedside
&lt;/h2&gt;

&lt;p&gt;When vitals are entered, a stacked ensemble (LightGBM, XGBoost, CatBoost, and an MLP) refines the ESI. Two things make it usable in a real department:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SHAP attributions&lt;/strong&gt;, so a clinician sees which features drove the score instead of a black-box number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split-conformal prediction sets&lt;/strong&gt;, so the model can say "I am not sure" with a real coverage guarantee rather than a fake confidence percentage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A deterministic safety floor sits on top: the system never down-triages a life threat, regardless of what the model thinks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it lives
&lt;/h2&gt;

&lt;p&gt;The refined ESI, the conformal set, and the top features are written back onto the patient record in DynamoDB, so the clinician cockpit reads a single, current source of truth in milliseconds. The cockpit and the patient app both deploy on Vercel and call the FastAPI-on-Lambda backend that fronts DynamoDB.&lt;/p&gt;

&lt;p&gt;The model never overrides the clinician. It hands them a defensible starting point, shows its work, and gets out of the way.&lt;/p&gt;

&lt;p&gt;I created this content for the purposes of entering the H0: Hack the Zero Stack hackathon. #H0Hackathon&lt;/p&gt;

</description>
      <category>aws</category>
      <category>machinelearning</category>
      <category>bedrock</category>
      <category>dynamodb</category>
    </item>
    <item>
      <title>Shipping a HIPAA-grade health app on Vercel + DynamoDB + Lambda</title>
      <dc:creator>Dhruv Jain</dc:creator>
      <pubDate>Mon, 29 Jun 2026 06:01:04 +0000</pubDate>
      <link>https://dev.to/dhruv_jain_8b924cc8f63fb8/shipping-a-hipaa-grade-health-app-on-vercel-dynamodb-lambda-37cg</link>
      <guid>https://dev.to/dhruv_jain_8b924cc8f63fb8/shipping-a-hipaa-grade-health-app-on-vercel-dynamodb-lambda-37cg</guid>
      <description>&lt;p&gt;Solace is an AI patient intake and triage app for emergency departments. Here is the full stack and why each piece is where it is. The whole thing runs on AWS managed services with the human-facing apps on Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  The request path
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Patient phone / Clinician (Vercel SPA)
        -&amp;gt; CloudFront + WAFv2
        -&amp;gt; API Gateway (HTTP)
        -&amp;gt; Lambda (FastAPI, arm64 container)
        -&amp;gt; DynamoDB, S3, Bedrock, Transcribe, Polly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cross-cutting: KMS CMK, Secrets Manager, CloudTrail, CloudWatch, EventBridge, SNS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vercel for the front door
&lt;/h2&gt;

&lt;p&gt;A patient checks in by scanning a QR code in the waiting room, with no app and no account. The patient app and the clinician terminal are static, edge-cached shells on Vercel that load fast on a weak waiting-room connection, then call the AWS backend. Branch-based atomic deploys mean I can ship the marketing site, the patient app, and the clinician app independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compute
&lt;/h2&gt;

&lt;p&gt;One FastAPI service (via Mangum) packaged as an ARM64 container image on AWS Lambda, 2048 MB, 60s timeout, Python 3.12 on AL2023, behind an HTTP API Gateway. The trained ML artifacts are baked into the image so cold starts do not pay a model-download tax. The registry is ECR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data
&lt;/h2&gt;

&lt;p&gt;Amazon DynamoDB is the primary datastore: about 30 tables, on demand, CMK-encrypted, with TTL on transient state (idempotency keys, session nonces, hot audit records). The live queue is a GSI on &lt;code&gt;hospital_id + created_at&lt;/code&gt;. Media lives in S3 with presigned delivery and public access blocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security and compliance
&lt;/h2&gt;

&lt;p&gt;Because it is healthcare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One CMK (&lt;code&gt;alias/solace&lt;/code&gt;) encrypts every DynamoDB table, the media bucket, the CloudTrail bucket, and Secrets Manager.&lt;/li&gt;
&lt;li&gt;WAFv2 on CloudFront runs Amazon IP Reputation, Known Bad Inputs, the OWASP Common Rule Set, and a rate-based rule capped at 50,000 requests per 5 minutes per IP (tuned for hospital NAT). Shield Standard is on.&lt;/li&gt;
&lt;li&gt;Every AI call routes through AWS Bedrock, Transcribe, and Polly, all covered by the AWS Business Associate Agreement, so no patient data leaves the BAA boundary and there are no separate vendor BAAs to chase.&lt;/li&gt;
&lt;li&gt;Clinicians authenticate by SMART-on-FHIR (OAuth + PKCE) or a PIN. IAM is least-privilege with an MFA permission boundary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point of the architecture is that a managed-service stack lets a small team ship something HIPAA-grade that still scales, rather than choosing between fast and real.&lt;/p&gt;

&lt;p&gt;I created this content for the purposes of entering the H0: Hack the Zero Stack hackathon. #H0Hackathon&lt;/p&gt;

</description>
      <category>aws</category>
      <category>vercel</category>
      <category>dynamodb</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Designing DynamoDB for an emergency department (access patterns first)</title>
      <dc:creator>Dhruv Jain</dc:creator>
      <pubDate>Mon, 29 Jun 2026 05:56:33 +0000</pubDate>
      <link>https://dev.to/dhruv_jain_8b924cc8f63fb8/designing-dynamodb-for-an-emergency-department-access-patterns-first-4ccp</link>
      <guid>https://dev.to/dhruv_jain_8b924cc8f63fb8/designing-dynamodb-for-an-emergency-department-access-patterns-first-4ccp</guid>
      <description>&lt;p&gt;I built Solace, an AI-native patient intake and triage app for emergency departments, on Amazon DynamoDB and Vercel. This post is about the part that's easy to get wrong: the data model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why DynamoDB for an ED
&lt;/h2&gt;

&lt;p&gt;An emergency department is the textbook DynamoDB workload. Traffic is bursty and unpredictable (a quiet floor, then six ambulances, then quiet again). Reads have to be single-digit-millisecond because the live patient queue refreshes on every arrival and a clinician is staring at it. And the access patterns are known in advance: look a patient up by id, a queue up by hospital, an encounter up by patient. That is exactly the shape DynamoDB is built for, and exactly the shape a relational database punishes you for under load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access patterns first, schema second
&lt;/h2&gt;

&lt;p&gt;I did not drop a normalized relational schema into DynamoDB. I listed every read the product actually performs, then built a deliberate multi-table design around them. About 30 tables, all on demand (PAY_PER_REQUEST) so I never plan capacity, all encrypted with one customer-managed KMS key.&lt;/p&gt;

&lt;p&gt;The most important one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;solace-patients&lt;/code&gt;: partition key &lt;code&gt;patient_id&lt;/code&gt;, plus a GSI on &lt;code&gt;hospital_id&lt;/code&gt; (hash) and &lt;code&gt;created_at&lt;/code&gt; (range).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That single GSI is the live queue. Query by hospital, sorted by arrival time, in milliseconds. The clinician cockpit reads it on every refresh.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three decisions that mattered
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exactly-once intake without transactions.&lt;/strong&gt; A patient on a flaky waiting-room connection will double-submit. Instead of a distributed transaction, the client sends a stable idempotency key and I store it in a TTL'd &lt;code&gt;solace-idempotency&lt;/code&gt; table. The same key lands once and returns the cached response on a retry. The TTL evicts the record after 24 hours, so there is no cleanup job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Self-expiring sessions.&lt;/strong&gt; &lt;code&gt;solace-intake-nonces&lt;/code&gt; uses DynamoDB TTL as the session lifetime. The database is the garbage collector.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Append-only audit, hot and cold.&lt;/strong&gt; &lt;code&gt;solace-audit-log&lt;/code&gt; is write-only with a 90-day TTL for hot access, and every record is also archived to S3 as CMK-encrypted JSONL with a lifecycle transition to Glacier, which is how I meet the HIPAA six-year retention requirement.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Vercel half
&lt;/h2&gt;

&lt;p&gt;The patient intake SPA and the clinician terminal deploy on Vercel as static, edge-cached shells that talk to the AWS backend (FastAPI on Lambda in front of DynamoDB). Fast to load on bad hospital Wi-Fi, atomic branch-based deploys.&lt;/p&gt;

&lt;p&gt;The payoff: the live queue and the EHR match return in single-digit milliseconds with zero capacity planning, and the design scales from one ED to many hospitals by adding partitions, not by re-architecting.&lt;/p&gt;




&lt;p&gt;I created this content for the purposes of entering the H0: Hack the Zero Stack hackathon. #H0Hackathon&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>dynamodb</category>
      <category>vercel</category>
    </item>
  </channel>
</rss>
