<?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: Aman </title>
    <description>The latest articles on DEV Community by Aman  (@amanm006).</description>
    <link>https://dev.to/amanm006</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%2F4004632%2F9ace8ac5-8bd3-4909-9237-80b334c30d22.jpg</url>
      <title>DEV Community: Aman </title>
      <link>https://dev.to/amanm006</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amanm006"/>
    <language>en</language>
    <item>
      <title>Building Sovereign: A Dual-Database Creator Liquidity Exchange on AWS Aurora DSQL + DynamoDB</title>
      <dc:creator>Aman </dc:creator>
      <pubDate>Fri, 26 Jun 2026 23:43:55 +0000</pubDate>
      <link>https://dev.to/amanm006/building-sovereign-a-transactional-creator-liquidity-exchange-on-aws-aurora-dsql-5327</link>
      <guid>https://dev.to/amanm006/building-sovereign-a-transactional-creator-liquidity-exchange-on-aws-aurora-dsql-5327</guid>
      <description>&lt;p&gt;Digital creators hold billions of dollars in illiquid assets - from newsletters and YouTube channels to SaaS repositories and Notion templates. How do you fractionalize ownership with instant, atomic trading settlements and absolute data integrity under heavy concurrent load?&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Sovereign&lt;/strong&gt;: a real-time Creator Liquidity Exchange built on a dual-database architecture - AWS Aurora DSQL for transactional correctness and Amazon DynamoDB for high-throughput telemetry.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Distributed Contention on the Order Book
&lt;/h2&gt;

&lt;p&gt;When multiple buyers attempt to match against the same resting sell orders concurrently, they generate a high-contention race condition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Over-Allocation Threat&lt;/strong&gt;: If two buy transactions read the same sell order's remaining balance simultaneously, both believe they can buy it. This creates phantom shares - double spending where total ledger allocation exceeds asset supply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Latency Trap&lt;/strong&gt;: Solving this with distributed locks slows execution significantly across regions, raising latency to hundreds of milliseconds.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Solution: Optimistic Concurrency Control with DSQL
&lt;/h2&gt;

&lt;p&gt;Instead of locking rows, Sovereign uses &lt;code&gt;SERIALIZABLE&lt;/code&gt; isolation on Aurora DSQL:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every matching event executes in a single database transaction. The engine reads counter-orders, computes fill quantities, and updates buyer and seller ledger rows atomically.&lt;/li&gt;
&lt;li&gt;If another transaction modified the order concurrently, DSQL throws a &lt;code&gt;40001&lt;/code&gt; serialization conflict. The engine catches it, applies jittered exponential backoff, and retries:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isOCCCollision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&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;cause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;40001&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serialization failure&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="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Retry loop&lt;/span&gt;
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&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="nf"&gt;attemptMatch&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="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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nf"&gt;isOCCCollision&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;continue&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="nx"&gt;err&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;h2&gt;
  
  
  Dual-Database Architecture
&lt;/h2&gt;

&lt;p&gt;The most important architectural decision: two databases, each doing what it's best at.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aurora DSQL (Stockholm, eu-north-1) - Transactional Core
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Orders, trades, ownership ledger, assets&lt;/li&gt;
&lt;li&gt;Requires &lt;code&gt;SERIALIZABLE&lt;/code&gt; isolation and global consistency&lt;/li&gt;
&lt;li&gt;OCC collision resolution IS the product mechanic&lt;/li&gt;
&lt;li&gt;Flat schema, no FK constraints (DSQL active-active requirement)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CREATE INDEX ASYNC&lt;/code&gt; (synchronous indexes not supported on distributed clusters)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Amazon DynamoDB (eu-north-1) - Activity Firehose
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Trade events, OCC collision logs, stampede telemetry&lt;/li&gt;
&lt;li&gt;Single-table design with 3 GSIs&lt;/li&gt;
&lt;li&gt;30-day TTL auto-expiry&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PAY_PER_REQUEST&lt;/code&gt; billing&lt;/li&gt;
&lt;li&gt;No transactions needed - pure append-only throughput DSQL for correctness. DynamoDB for throughput.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every trade fires a fire-and-forget write to DynamoDB:&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;// After successful DSQL match - never blocks critical path&lt;/span&gt;
&lt;span class="nf"&gt;writeFirehose&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;eventType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;TRADE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;assetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sharesTraded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priceExecuted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;latencyMs&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&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;// silent fail - DynamoDB is best-effort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  System Architecture Flow
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              ┌───────────────────────────────┐
              │      Client Web App (UI)      │
              └───────────────┬───────────────┘
                              │ HTTPS / SSE
                              ▼
              ┌───────────────────────────────┐
              │     Next.js Server Actions    │
              └───────┬───────────────┬───────┘
                      │               │
  Serializable Tx     │               │ Async Telemetry Write
 (Postgres pg client) │               │ (AWS SDK PutCommand)
                      ▼               ▼
              ┌───────────────┐┌───────────────┐
              │  OCC Engine   ││  DynamoDB     │
              │  (Aurora DSQL)││  Firehose     │
              └───────────────┘└───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Stress Testing: The Stampede Load Simulator
&lt;/h2&gt;

&lt;p&gt;To prove integrity under load, we built a stampede simulator:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Seed 100 sell orders from market-maker&lt;/li&gt;
&lt;li&gt;Fire 100 concurrent buy orders simultaneously&lt;/li&gt;
&lt;li&gt;DSQL generates serialization failures - engine retries with jitter&lt;/li&gt;
&lt;li&gt;Audit: &lt;code&gt;SUM(shares_owned)&lt;/code&gt; must equal &lt;code&gt;total_shares&lt;/code&gt; exactly&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Recent Run Results:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Settled&lt;/strong&gt;: 100/100 orders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCC Collisions Resolved&lt;/strong&gt;: 432&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time elapsed&lt;/strong&gt;: 1,450ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Balance Delta&lt;/strong&gt;: 0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit Verdict&lt;/strong&gt;: ✅ PASSED - ZERO OVER-ALLOCATION&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mathematical proof: if two buyers both got share #47, delta would be nonzero. Delta is always 0. DSQL OCC makes this impossible.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Implementation Challenges
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Drizzle wraps native errors&lt;/strong&gt;: Drizzle puts the real Postgres error in &lt;code&gt;err.cause&lt;/code&gt;, not &lt;code&gt;err&lt;/code&gt; directly. Our retry loop initially missed all &lt;code&gt;40001&lt;/code&gt; codes. Fix: inspect &lt;code&gt;err.cause?.code&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DSQL DDL restrictions&lt;/strong&gt;: No &lt;code&gt;SERIAL&lt;/code&gt; types, no synchronous indexes. Required a custom migration runner using &lt;code&gt;CREATE INDEX ASYNC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel timeout&lt;/strong&gt;: 300 concurrent orders to Stockholm DSQL exceeded Vercel's 60s function timeout. Restructured to 3 batches of 20 with timeout escape hatch.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Live Demo &amp;amp; Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://sovereign-dex.vercel.app/" rel="noopener noreferrer"&gt;sovereign-dex.vercel.app&lt;/a&gt; - click &lt;strong&gt;DEMO LOGIN&lt;/strong&gt;, no signup needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run Stampede&lt;/strong&gt;: Hit &lt;strong&gt;RUN STAMPEDE&lt;/strong&gt; in the telemetry console to see OCC collisions resolve live. Watch the DynamoDB activity feed populate on the market home page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/AmanM006/sovereign" rel="noopener noreferrer"&gt;AmanM006/sovereign&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;I created this article for the H0: Hack the Zero Stack hackathon.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>nextjs</category>
      <category>database</category>
      <category>h0hackathon</category>
    </item>
  </channel>
</rss>
