<?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: M Rayhan Khan</title>
    <description>The latest articles on DEV Community by M Rayhan Khan (@m_rayhankhan_71c3f2ed50c).</description>
    <link>https://dev.to/m_rayhankhan_71c3f2ed50c</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%2F2600954%2F7ddf4ee1-70f8-4357-9af8-4187ed38c05a.png</url>
      <title>DEV Community: M Rayhan Khan</title>
      <link>https://dev.to/m_rayhankhan_71c3f2ed50c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m_rayhankhan_71c3f2ed50c"/>
    <language>en</language>
    <item>
      <title>How I built a flash-sale engine that can't oversell</title>
      <dc:creator>M Rayhan Khan</dc:creator>
      <pubDate>Sat, 13 Jun 2026 05:25:43 +0000</pubDate>
      <link>https://dev.to/m_rayhankhan_71c3f2ed50c/how-i-built-a-flash-sale-engine-that-cant-oversell-even-at-1000-concurrent-buyers-34p5</link>
      <guid>https://dev.to/m_rayhankhan_71c3f2ed50c/how-i-built-a-flash-sale-engine-that-cant-oversell-even-at-1000-concurrent-buyers-34p5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;I created this piece of content for the purpose of entering the &lt;strong&gt;H0: Hack the Zero Stack&lt;/strong&gt; hackathon. #H0Hackathon&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The problem (that's harder than it sounds)
&lt;/h2&gt;

&lt;p&gt;"Don't sell more tickets than you have" sounds trivial until 10,000 people click &lt;strong&gt;Buy&lt;/strong&gt; in the same second.&lt;/p&gt;

&lt;p&gt;The naive fix — a single &lt;code&gt;remaining&lt;/code&gt; counter you decrement on every purchase — falls apart under load. And when you try to go multi-region, it gets worse: with eventual consistency across regions you can oversell during the replication window.&lt;/p&gt;

&lt;p&gt;I wanted a flash-sale engine that is &lt;strong&gt;globally fast AND strongly consistent AND operationally simple&lt;/strong&gt; — all three. That combination is precisely what &lt;strong&gt;Amazon Aurora DSQL&lt;/strong&gt; is built for, so I built &lt;strong&gt;DropZero&lt;/strong&gt; on it for the hackathon.&lt;/p&gt;




&lt;h2&gt;
  
  
  The trap I almost walked into
&lt;/h2&gt;

&lt;p&gt;Aurora DSQL is a serverless, PostgreSQL-compatible, multi-region active-active SQL database. Crucially, it uses &lt;strong&gt;optimistic concurrency control (OCC)&lt;/strong&gt;: transactions run without locks, and conflicts are detected at commit time — the loser gets a &lt;code&gt;SQLSTATE 40001&lt;/code&gt; serialization error and retries.&lt;/p&gt;

&lt;p&gt;That detail flips the "obvious" design on its head. A single hot counter row that every buyer updates is the &lt;strong&gt;worst&lt;/strong&gt; workload for OCC. Thousands of writes to one key collide at commit time, and you get a retry storm that eats your throughput. AWS's own documentation is explicit: spread writes across the key range.&lt;/p&gt;




&lt;h2&gt;
  
  
  The design that actually works
&lt;/h2&gt;

&lt;p&gt;Instead of a counter, &lt;strong&gt;model each sellable unit as its own database row&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;drop_units&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;         &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="n"&gt;drop_id&lt;/span&gt;    &lt;span class="n"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;unit_no&lt;/span&gt;    &lt;span class="nb"&gt;integer&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;status&lt;/span&gt;     &lt;span class="nb"&gt;text&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="s1"&gt;'available'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;-- available | claimed&lt;/span&gt;
  &lt;span class="n"&gt;order_id&lt;/span&gt;   &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;claimed_at&lt;/span&gt; &lt;span class="n"&gt;timestamptz&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each buyer &lt;strong&gt;claims a random distinct unit&lt;/strong&gt; in one strongly-consistent transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/store-dsql.ts (simplified)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;reserveUnit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dropId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;withRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Find a random available unit, claim it atomically&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`SELECT id FROM drop_units
          WHERE drop_id = $1 AND status = 'available'
          ORDER BY random() LIMIT 5`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dropId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SOLD_OUT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// Race for one — OCC means only one wins per row&lt;/span&gt;
      &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="s2"&gt;`UPDATE drop_units
              SET status = 'claimed', order_id = $1, claimed_at = now()
            WHERE id = $2 AND status = 'available'
            RETURNING unit_no`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rowCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RETRY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;unit_no&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;withRetry&lt;/code&gt; only re-runs on &lt;code&gt;SQLSTATE 40001&lt;/code&gt; (OCC conflict), with jittered exponential backoff. Everything else surfaces immediately.&lt;/p&gt;

&lt;p&gt;Two properties fall out of this design for free:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Overselling is impossible by construction.&lt;/strong&gt; Each row transitions &lt;code&gt;available → claimed&lt;/code&gt; at most once, enforced by the &lt;code&gt;WHERE status = 'available'&lt;/code&gt; predicate in a strongly-consistent transaction. So &lt;code&gt;claimed ≤ total&lt;/code&gt; always holds — regardless of region count or traffic spike.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conflicts stay near zero.&lt;/strong&gt; Because buyers target &lt;em&gt;random&lt;/em&gt; rows, 5,000 simultaneous buyers touch ~5,000 &lt;em&gt;different&lt;/em&gt; rows. DSQL is optimized for exactly this write pattern. The few genuine collisions (two buyers picking the same random row) are retried transparently.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  An extra layer: idempotency
&lt;/h2&gt;

&lt;p&gt;Double-clicks and network retries can cause a buyer to send the same request twice. I added a unique index on &lt;code&gt;idempotency_key&lt;/code&gt; in the &lt;code&gt;orders&lt;/code&gt; table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;orders_idempotency_key&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;idempotency_key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The claim function checks this first — if the key already produced an order, return it. A double-click never double-buys.&lt;/p&gt;




&lt;h2&gt;
  
  
  Proving it: the stampede simulator
&lt;/h2&gt;

&lt;p&gt;DropZero ships with a built-in concurrency simulator. Click &lt;strong&gt;Run stampede&lt;/strong&gt;, choose a buyer count and a drop with limited inventory, and the app fires that many concurrent purchase requests.&lt;/p&gt;

&lt;p&gt;Result for &lt;strong&gt;1,000 buyers racing for 200 units&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;confirmed:   200   (exactly the inventory)
rejected:    800   (clean SOLD_OUT, not errors)
oversold:      0
conflicts:     2   (OCC retries, resolved transparently)
p99 latency: 42ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time. The "integrity proof" button runs a live &lt;code&gt;SELECT COUNT(*)&lt;/code&gt; grouped by status to confirm &lt;code&gt;claimed = 200&lt;/code&gt; and &lt;code&gt;available = 0&lt;/code&gt; with no ghost rows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Aurora DSQL specifically
&lt;/h2&gt;

&lt;p&gt;Other databases could prevent overselling — but usually with trade-offs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Single-region RDS with row locks&lt;/td&gt;
&lt;td&gt;Locks under high concurrency → queue → latency spike&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redis DECR with Lua&lt;/td&gt;
&lt;td&gt;Fast but not durable by default; adding durability adds complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB conditional writes&lt;/td&gt;
&lt;td&gt;No SQL; harder to model the relational parts (orders, seller analytics)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CockroachDB / Spanner&lt;/td&gt;
&lt;td&gt;Great, but operational overhead; not serverless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Aurora DSQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Serverless, PostgreSQL SQL, multi-region active-active, strongly consistent, zero ops&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;DSQL specifically solves the "global buyers, one inventory" problem without a waiting room, without a single write bottleneck, and without giving up strong consistency. It's the right tool for this workload.&lt;/p&gt;




&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Next.js 14 (App Router) + Tailwind CSS + SWR for live polling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API&lt;/td&gt;
&lt;td&gt;Next.js Route Handlers (Node runtime)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Amazon Aurora DSQL&lt;/strong&gt; — serverless, multi-region, PostgreSQL-compatible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB auth&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pg&lt;/code&gt; driver + &lt;code&gt;@aws-sdk/dsql-signer&lt;/code&gt; — IAM auth tokens, no stored passwords&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; + Vercel Marketplace OIDC integration (keyless AWS access)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The OIDC integration is worth calling out: Vercel assumes an AWS IAM role per deployment. No &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; or &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; anywhere in the project. Zero stored credentials.&lt;/p&gt;




&lt;h2&gt;
  
  
  One schema note: DSQL doesn't support foreign keys or synchronous indexes
&lt;/h2&gt;

&lt;p&gt;DSQL is not vanilla PostgreSQL. I hit two constraints that shaped the schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No foreign keys.&lt;/strong&gt; &lt;code&gt;orders.drop_id&lt;/code&gt; and &lt;code&gt;drop_units.drop_id&lt;/code&gt; are logical references enforced in application code, not DB constraints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indexes must be &lt;code&gt;CREATE INDEX ASYNC&lt;/code&gt;.&lt;/strong&gt; The &lt;code&gt;db:init&lt;/code&gt; script auto-rewrites &lt;code&gt;CREATE INDEX&lt;/code&gt; → &lt;code&gt;CREATE INDEX ASYNC&lt;/code&gt; when it detects a DSQL endpoint. Otherwise the migration hangs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batched inserts under 10k rows/txn.&lt;/strong&gt; When minting units for a large drop, inserts are batched in chunks of 500.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are reasonable constraints for what DSQL gives you in return.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://dropzero.vercel.app" rel="noopener noreferrer"&gt;https://dropzero.vercel.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/mrayhankhan/dropzero" rel="noopener noreferrer"&gt;https://github.com/mrayhankhan/dropzero&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app runs in zero-credential preview mode (in-memory) by default, so you can poke around without an AWS account. The badge in the header tells you which mode you're in.&lt;/p&gt;




&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Distributed databases don't remove the hard parts of concurrency — they move them into your data model. Aurora DSQL's OCC model is powerful, but it punishes designs with hot rows and rewards designs with spread-out writes.&lt;/p&gt;

&lt;p&gt;Turn one hot counter into many cool unit rows, and a gnarly distributed-systems problem becomes a dozen lines of SQL — with a mathematically provable guarantee baked in.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for the &lt;a href="https://h01.devpost.com" rel="noopener noreferrer"&gt;H0: Hack the Zero Stack&lt;/a&gt; hackathon — Track 3 (Million-scale Global App). #H0Hackathon&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>postgres</category>
      <category>nextjs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How I built a dependency risk scanner with Coral</title>
      <dc:creator>M Rayhan Khan</dc:creator>
      <pubDate>Sat, 30 May 2026 18:33:39 +0000</pubDate>
      <link>https://dev.to/m_rayhankhan_71c3f2ed50c/how-i-built-a-dependency-risk-scanner-with-coral-in-7-days-4p9</link>
      <guid>https://dev.to/m_rayhankhan_71c3f2ed50c/how-i-built-a-dependency-risk-scanner-with-coral-in-7-days-4p9</guid>
      <description>&lt;h2&gt;
  
  
  Why this project
&lt;/h2&gt;

&lt;p&gt;Every developer has 5-10 side projects with rotting dependencies and doesn't know it. The 2024 xz-utils backdoor was caught &lt;strong&gt;by accident&lt;/strong&gt; — one engineer noticed SSH was 500 ms slower than usual. That's how close it came.&lt;/p&gt;

&lt;p&gt;Tools like Snyk and Dependabot catch known CVEs after they're published. Nothing checks the three signals that &lt;em&gt;together&lt;/em&gt; predict a future supply-chain attack: &lt;strong&gt;active CVEs · abandoned maintainer · collapsing downloads&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That three-way signal only exists if you can JOIN across &lt;strong&gt;OSV&lt;/strong&gt; (Google's vulnerability database), the &lt;strong&gt;npm registry&lt;/strong&gt;, and the &lt;strong&gt;npm download API&lt;/strong&gt;. Which is exactly what Coral does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The query the whole project is built around
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;latest_version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repository__url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time__modified&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;last_publish_at&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;packages&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;package_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;cves&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;affected__package__name&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;package_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;cve_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;CASE&lt;/span&gt; &lt;span class="n"&gt;database_specific__severity&lt;/span&gt;
               &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'CRITICAL'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'HIGH'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
               &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'MODERATE'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="s1"&gt;'LOW'&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;ELSE&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;worst_sev_rank&lt;/span&gt;
  &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;osv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vulnerabilities&lt;/span&gt;
  &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;package_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;ecosystem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'npm'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;withdrawn&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
  &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;affected__package__name&lt;/span&gt;
&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="n"&gt;dl_month&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;downloads&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;npm_downloads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downloads_last_month&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;package_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;pkg&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cve_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;cve_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;COALESCE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;worst_sev_rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;worst_severity_rank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;dl_month&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;downloads&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;cves&lt;/span&gt;     &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;cves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;package_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dl_month&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One query. Three live systems — three different hosts (&lt;code&gt;registry.npmjs.org&lt;/code&gt;, &lt;code&gt;api.osv.dev&lt;/code&gt;, &lt;code&gt;api.npmjs.org&lt;/code&gt;). Zero glue code. &lt;strong&gt;No ChatGPT instance on earth can run this.&lt;/strong&gt; Verified against &lt;code&gt;minimist&lt;/code&gt;: 2 CVEs, worst severity CRITICAL, 531M downloads/month.&lt;/p&gt;

&lt;h2&gt;
  
  
  The OSV source spec
&lt;/h2&gt;

&lt;p&gt;OSV is a public REST API. The Coral source spec is a single YAML file, and the skeleton came together quickly. The hard part started right after.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;vulnerabilities&lt;/code&gt; table uses &lt;code&gt;POST /v1/query&lt;/code&gt;. Two things bit me, and both were about &lt;em&gt;reading the response shape correctly&lt;/em&gt; rather than writing YAML:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The &lt;code&gt;__&lt;/code&gt; flatten convention isn't automatic.&lt;/strong&gt; I assumed a column named &lt;code&gt;database_specific__severity&lt;/code&gt; would auto-resolve the nested &lt;code&gt;database_specific.severity&lt;/code&gt;. It didn't — it came back &lt;code&gt;null&lt;/code&gt;. Nested fields need an explicit &lt;code&gt;expr&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database_specific__severity&lt;/span&gt;
     &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Utf8&lt;/span&gt;
     &lt;span class="na"&gt;expr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
       &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path&lt;/span&gt;
       &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;database_specific&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Array indexing uses string keys.&lt;/strong&gt; To lift the package name out of the &lt;code&gt;affected[]&lt;/code&gt; array as a JOIN key, the path is &lt;code&gt;[affected, "0", package, name]&lt;/code&gt; — &lt;code&gt;"0"&lt;/code&gt; as a &lt;em&gt;string&lt;/em&gt;, not an integer (the integer form fails schema validation).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;coral source lint&lt;/code&gt; caught my structural mistakes offline; the nested-path mistakes only showed up when I ran a real query against &lt;code&gt;lodash&lt;/code&gt; and &lt;code&gt;minimist&lt;/code&gt; and saw &lt;code&gt;null&lt;/code&gt; columns. No tool tells you that — you have to diff the response against your spec by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  The npm specs (note the plural)
&lt;/h2&gt;

&lt;p&gt;This is where I learned the most. npm is really two APIs: &lt;code&gt;registry.npmjs.org&lt;/code&gt; for package metadata and &lt;code&gt;api.npmjs.org&lt;/code&gt; for download counts. My first instinct was one source spec with a per-table &lt;code&gt;base_url&lt;/code&gt; override.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That field doesn't exist.&lt;/strong&gt; A Coral source has exactly one &lt;code&gt;base_url&lt;/code&gt;. The clean fix turned out to be better than the hack: &lt;strong&gt;two source specs&lt;/strong&gt;. &lt;code&gt;npm.yaml&lt;/code&gt; (the &lt;code&gt;packages&lt;/code&gt; table) and &lt;code&gt;npm_downloads.yaml&lt;/code&gt; (&lt;code&gt;downloads_last_month&lt;/code&gt; + &lt;code&gt;downloads_last_week&lt;/code&gt;). That's not a workaround — it's a second genuinely reusable spec, and it doubled my bounty surface area.&lt;/p&gt;

&lt;p&gt;The other lesson: a declared &lt;code&gt;filter&lt;/code&gt; must &lt;em&gt;also&lt;/em&gt; be declared as a column for &lt;code&gt;WHERE package_name = ...&lt;/code&gt; to resolve, and the filter value isn't echoed back automatically — so JOINs key off real returned columns (&lt;code&gt;npm.packages.name&lt;/code&gt;, &lt;code&gt;downloads.package&lt;/code&gt;, &lt;code&gt;osv.affected__package__name&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The fan-out
&lt;/h2&gt;

&lt;p&gt;The auditor reads &lt;code&gt;package.json&lt;/code&gt; from a GitHub raw URL, collects every dependency (including devDependencies — supply-chain attacks via dev tools are real, see event-stream), and runs the query once per dep with 6-way concurrency. &lt;code&gt;chalk/chalk&lt;/code&gt; finished in ~17 seconds. &lt;code&gt;lib/concurrency.ts&lt;/code&gt; is 30 lines.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dashboard
&lt;/h2&gt;

&lt;p&gt;Three columns: 🟢 healthy / 🟡 watch / 🔴 danger. Click a card → drill-down with every signal and a direct link to the OSV record. The whole UI is in &lt;a href="//./app/components/"&gt;&lt;code&gt;app/components/&lt;/code&gt;&lt;/a&gt; — three files, all client components, Tailwind for styling. GitHub maintainer-activity (last push, archived) is layered on top via the bundled &lt;code&gt;github&lt;/code&gt; source when a token is present — deliberately kept &lt;em&gt;out&lt;/em&gt; of the headline query so the demo runs with zero auth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scoring rules
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;lib/risk.ts&lt;/code&gt; is a pure function, and the scoring rules are the part I most wanted to get right by hand — this is product judgment, not codegen. Easy to unit-test. Rules I landed on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CVE HIGH/CRITICAL → instant danger.&lt;/strong&gt; No nuance needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale + collapsing → danger.&lt;/strong&gt; Maintainer silent &amp;gt; 1 year AND downloads down &amp;gt; 30%. This is the xz-utils pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale OR declining → watch.&lt;/strong&gt; Either alone is a yellow flag, not red.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Otherwise → healthy.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The compound rule was the one that took the most reading. A package can have no CVE filed yet and still be the most dangerous thing in your repo if the maintainer has gone dark.&lt;/p&gt;

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

&lt;p&gt;I built a transparent HTTP fallback (&lt;code&gt;lib/coral.ts&lt;/code&gt; path B) so the demo doesn't break on a laptop without Coral installed. &lt;strong&gt;Same data, same row shape&lt;/strong&gt;, just bypassing the CLI. The header shows &lt;code&gt;coral CLI&lt;/code&gt; vs &lt;code&gt;direct HTTP fallback&lt;/code&gt; so judges can see which path is active. The fallback is a safety net; Coral is the production engine.&lt;/p&gt;

&lt;p&gt;One subtlety that cost me an hour: Coral's SQL engine is DataFusion, not SQLite. So &lt;code&gt;julianday()&lt;/code&gt; and &lt;code&gt;json_group_array()&lt;/code&gt; don't exist — the date math is &lt;code&gt;date_part('day', now() - to_timestamp(col))&lt;/code&gt; and the CVE list is &lt;code&gt;array_agg(named_struct(...))&lt;/code&gt;. Worth knowing before you write the query.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Three insights I didn't expect:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The hard part of source specs isn't writing them — it's reading the API docs accurately.&lt;/strong&gt; Scaffolding the YAML is fast (with or without an assistant). I spent far more time confirming OSV's nested field paths against real responses than authoring the spec. Every &lt;code&gt;null&lt;/code&gt; column was a docs-reading miss, not a syntax error — and no tool catches those for you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The cross-source JOIN really does feel like magic in the terminal.&lt;/strong&gt; Three completely separate systems, one result set, one query. The demo moment isn't the dashboard — it's the &lt;code&gt;coral sql&lt;/code&gt; invocation. Everyone leans forward.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pure scoring functions are worth their weight in unit tests.&lt;/strong&gt; Once &lt;code&gt;lib/risk.ts&lt;/code&gt; was unit-tested I could change the rules without fear. The 12 tests in &lt;code&gt;risk.test.ts&lt;/code&gt; caught two regressions during the hackathon.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The repo is on GitHub. Three custom source specs, one Next.js app, MIT licensed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/mrayhankhan/CoralBean.git
bash scripts/install-coral.sh
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste &lt;code&gt;facebook/react&lt;/code&gt; (mostly green) or &lt;code&gt;chalk/chalk&lt;/code&gt; (watch &lt;code&gt;color-convert&lt;/code&gt; go red) and watch.&lt;/p&gt;

&lt;p&gt;🏴‍☠️&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
