<?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: Yarra Vivek</title>
    <description>The latest articles on DEV Community by Yarra Vivek (@yarra_vivek).</description>
    <link>https://dev.to/yarra_vivek</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%2F3990296%2F8f0669b4-39a2-4997-a3a5-8b547f668359.png</url>
      <title>DEV Community: Yarra Vivek</title>
      <link>https://dev.to/yarra_vivek</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yarra_vivek"/>
    <language>en</language>
    <item>
      <title>I built an AI agent that found a critical bug a human reviewer would've missed published: true</title>
      <dc:creator>Yarra Vivek</dc:creator>
      <pubDate>Sun, 21 Jun 2026 12:40:09 +0000</pubDate>
      <link>https://dev.to/yarra_vivek/i-built-an-ai-agent-that-found-a-critical-bug-a-human-reviewer-wouldve-missedpublished-true-180f</link>
      <guid>https://dev.to/yarra_vivek/i-built-an-ai-agent-that-found-a-critical-bug-a-human-reviewer-wouldve-missedpublished-true-180f</guid>
      <description>&lt;h2&gt;
  
  
  The diff looked harmless
&lt;/h2&gt;

&lt;p&gt;A teammate changes a function's return type. &lt;code&gt;bool&lt;/code&gt; becomes &lt;code&gt;dict&lt;/code&gt;. &lt;br&gt;
Looks like a minor improvement — more detail in the response, why not?&lt;/p&gt;

&lt;p&gt;Three files away, that one-line change quietly breaks payment validation.&lt;/p&gt;

&lt;p&gt;This is the exact scenario I built &lt;strong&gt;Tripwire&lt;/strong&gt; to catch.&lt;/p&gt;
&lt;h2&gt;
  
  
  What Tripwire does
&lt;/h2&gt;

&lt;p&gt;Tripwire is a GitLab Duo agent + custom flow built on &lt;strong&gt;GitLab Orbit&lt;/strong&gt; — &lt;br&gt;
GitLab's knowledge graph that maps real relationships across your &lt;br&gt;
codebase, not just file contents.&lt;/p&gt;

&lt;p&gt;Assign Tripwire as a reviewer on any merge request, and it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traces the actual dependency chain of every changed function&lt;/li&gt;
&lt;li&gt;Finds downstream callers that aren't even part of the diff&lt;/li&gt;
&lt;li&gt;Checks for open security findings in those code paths&lt;/li&gt;
&lt;li&gt;Posts a structured risk report directly on the MR&lt;/li&gt;
&lt;li&gt;Suggests who should &lt;em&gt;actually&lt;/em&gt; review it, based on code ownership&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No chat window. No copy-pasting a prompt. Assign it like a teammate, &lt;br&gt;
and it runs.&lt;/p&gt;
&lt;h2&gt;
  
  
  The bug it actually caught
&lt;/h2&gt;

&lt;p&gt;I built a tiny test codebase with a real dependency chain:&lt;br&gt;
notifications.py → payments.py → validation.py&lt;/p&gt;

&lt;p&gt;Then I opened an MR that changed &lt;code&gt;validate_card()&lt;/code&gt;'s return type from &lt;br&gt;
&lt;code&gt;bool&lt;/code&gt; to &lt;code&gt;dict&lt;/code&gt;. The MR looked clean. One file changed. Reasonable-looking diff.&lt;/p&gt;

&lt;p&gt;Tripwire flagged it &lt;strong&gt;CRITICAL&lt;/strong&gt; and said: don't merge this.&lt;/p&gt;

&lt;p&gt;Here's why. In Python, &lt;strong&gt;any non-empty dict is truthy&lt;/strong&gt; — regardless &lt;br&gt;
of what's inside it. So this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;validate_card&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card_number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...now always evaluates to &lt;code&gt;True&lt;/code&gt;. Even for an invalid card. Silently. &lt;br&gt;
No exception. No test failure unless you specifically assert on the &lt;br&gt;
return type. Just a payment that should have been rejected, going &lt;br&gt;
through anyway.&lt;/p&gt;

&lt;p&gt;It also caught a second, smaller issue I hadn't even been thinking &lt;br&gt;
about: the new logic only accepts 16-digit cards. American Express &lt;br&gt;
(15 digits) got silently dropped, with zero mention in the MR description.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building on a beta platform means assumptions break constantly
&lt;/h2&gt;

&lt;p&gt;Half of what I assumed going in turned out to be wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There's no &lt;code&gt;merge_request:opened&lt;/code&gt; trigger (yet) — flows trigger on 
mention, assignment, or being assigned as reviewer&lt;/li&gt;
&lt;li&gt;Custom agents aren't defined in a repo file — they're created through 
the AI Catalog UI directly&lt;/li&gt;
&lt;li&gt;Orbit's API isn't a set of clean REST routes per resource type — it's 
one generic graph query endpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of these required throwing out an assumption and rebuilding &lt;br&gt;
against what the platform actually does, not what seemed like the &lt;br&gt;
obvious design.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;🔗 &lt;a href="https://gitlab.com/explore/ai-catalog/agents/1011391/" rel="noopener noreferrer"&gt;Tripwire agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;a href="https://gitlab.com/explore/ai-catalog/flows/1011394/" rel="noopener noreferrer"&gt;mr-risk-analyzer flow&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;a href="https://gitlab.com/gitlab-ai-hackathon/transcend/39012371" rel="noopener noreferrer"&gt;Source project&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🔗 &lt;a href="https://gitlab.com/gitlab-ai-hackathon/transcend/39012371/-/merge_requests/3" rel="noopener noreferrer"&gt;The actual MR it flagged&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built for the GitLab Transcend Hackathon, powered by GitLab Orbit.&lt;/p&gt;

</description>
      <category>gitlab</category>
      <category>ai</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Yarra Vivek</dc:creator>
      <pubDate>Sat, 20 Jun 2026 01:57:09 +0000</pubDate>
      <link>https://dev.to/yarra_vivek/-mc4</link>
      <guid>https://dev.to/yarra_vivek/-mc4</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d" class="crayons-story__hidden-navigation-link"&gt;Why I Used DynamoDB AND Aurora PostgreSQL Together — Not Just One (Built for H0: Hack the Zero Stack with Vercel v0 and AWS Databases)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/yarra_vivek" class="crayons-avatar  crayons-avatar--l  "&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3990296%2F8f0669b4-39a2-4997-a3a5-8b547f668359.png" alt="yarra_vivek profile" class="crayons-avatar__image" width="96" height="96"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/yarra_vivek" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Yarra Vivek
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Yarra Vivek
                
              
              &lt;div id="story-author-preview-content-3932626" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/yarra_vivek" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3990296%2F8f0669b4-39a2-4997-a3a5-8b547f668359.png" class="crayons-avatar__image" alt="" width="96" height="96"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Yarra Vivek&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 18&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d" id="article-link-3932626"&gt;
          Why I Used DynamoDB AND Aurora PostgreSQL Together — Not Just One (Built for H0: Hack the Zero Stack with Vercel v0 and AWS Databases)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/postgressql"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;postgressql&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Why I Used DynamoDB AND Aurora PostgreSQL Together — Not Just One (Built for H0: Hack the Zero Stack with Vercel v0 and AWS Databases)</title>
      <dc:creator>Yarra Vivek</dc:creator>
      <pubDate>Thu, 18 Jun 2026 12:44:44 +0000</pubDate>
      <link>https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d</link>
      <guid>https://dev.to/yarra_vivek/why-i-used-dynamodb-and-aurora-postgresql-together-not-just-one-built-for-h0-hack-the-zero-2n4d</guid>
      <description>&lt;p&gt;I made a mistake that most developers make when starting a new project.&lt;br&gt;
I opened the AWS console, looked at the database options, and thought: "I just need to pick one."&lt;br&gt;
Two weeks later, after building STRATUM — a real-time neighborhood intelligence platform — I understand why that instinct is wrong. Not slightly wrong. Fundamentally wrong for a certain class of application.&lt;br&gt;
This is the story of why I ended up using both DynamoDB and Aurora PostgreSQL, what almost made me collapse them into one, and what the experience taught me about database architecture that I won't forget.&lt;/p&gt;

&lt;p&gt;What STRATUM does&lt;br&gt;
STRATUM lets residents anonymously drop geo-tagged signals about their neighborhood in 15 seconds — a flooded road, a new coffee shop, an unsafe corner at night, a construction site that starts at 6am. The app clusters thousands of these signals into live "layers" on a map: Safety, Vibe, Infrastructure, Opportunity.&lt;br&gt;
Three types of users interact with it:&lt;/p&gt;

&lt;p&gt;Residents report and explore for free&lt;br&gt;
Real estate agents pay $49/month for neighborhood trend APIs&lt;br&gt;
City governments pay $299/month for infrastructure dashboards&lt;/p&gt;

&lt;p&gt;Live app: &lt;a href="https://stratum-rho-green.vercel.app" rel="noopener noreferrer"&gt;https://stratum-rho-green.vercel.app&lt;/a&gt;&lt;br&gt;
Here's what the map looks like with real data across San Francisco:&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq55ig9yjnypjvscq6kmu.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq55ig9yjnypjvscq6kmu.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here's the neighborhood score card that appears when you click any cluster:&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3tezvfmv2klshau34ydt.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3tezvfmv2klshau34ydt.png" alt=" " width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The naive version: just use one database&lt;br&gt;
My first instinct was DynamoDB for everything. The scale story is obvious — DynamoDB handles millions of writes per second, it's fully managed, it never goes down. For a platform where anyone in the world can submit a report at any moment, that write scalability is genuinely important.&lt;br&gt;
The problem showed up when I tried to answer questions like:&lt;/p&gt;

&lt;p&gt;"What is the average safety score for all neighborhoods in San Francisco over the last 7 days?"&lt;br&gt;
"Which neighborhoods have seen a 30% increase in infrastructure reports this month?"&lt;br&gt;
"Show me all API keys, their usage this month, and whether their subscription is still active"&lt;/p&gt;

&lt;p&gt;DynamoDB is not built for these questions. It's built for "give me this specific item by its key." Analytical queries that scan across many items, join data from multiple entities, and aggregate over time ranges — these are expensive and awkward in DynamoDB. You can technically do them, but you're working against the grain of the database every single time.&lt;br&gt;
So I tried the other direction: Aurora PostgreSQL for everything. Rich relational queries, SQL, the full power of a real database engine.&lt;br&gt;
The problem showed up immediately. Every anonymous resident report is a write. In a city with millions of residents, those writes are constant, high-volume, and completely unpredictable in timing. Aurora PostgreSQL scales, but it scales differently — it needs connection pooling, it has cold start latency on serverless, and the cost model for millions of small writes is painful compared to DynamoDB.&lt;br&gt;
More critically: a resident submitting a report should feel instant. Sub-100ms. Serverless Aurora adds latency that DynamoDB simply doesn't have.&lt;/p&gt;

&lt;p&gt;The insight: these are two genuinely different problems&lt;br&gt;
Here's the moment everything clicked.&lt;br&gt;
The report submission flow and the analytics flow have completely different shapes:&lt;br&gt;
WRITE PATH (report submission):&lt;/p&gt;

&lt;p&gt;Extremely high volume at scale&lt;br&gt;
Simple structure: one report, known fields, no joins needed&lt;br&gt;
Needs to be fast everywhere in the world simultaneously&lt;br&gt;
Data is naturally partitioned by geography&lt;br&gt;
Old reports can expire — nobody needs 5-year-old noise complaints&lt;/p&gt;

&lt;p&gt;READ PATH (analytics and intelligence):&lt;/p&gt;

&lt;p&gt;Lower volume but complex queries&lt;br&gt;
Requires aggregation, trends, comparisons across many records&lt;br&gt;
Needs relational integrity — users linked to subscriptions linked to API keys linked to usage logs&lt;br&gt;
Data needs to persist and compound over time&lt;/p&gt;

&lt;p&gt;These aren't two versions of the same problem. They're genuinely different problems that happen to live in the same application.&lt;br&gt;
This is a pattern called CQRS — Command Query Responsibility Segregation. The basic idea: separate the write model from the read model. Don't force one database to be good at both things. Let each database do what it was actually built to do.&lt;/p&gt;

&lt;p&gt;The actual implementation&lt;br&gt;
Here's how data flows through STRATUM:&lt;br&gt;
POST /api/reports&lt;br&gt;
    │&lt;br&gt;
    ▼&lt;br&gt;
AWS DynamoDB — stratum-reports table&lt;br&gt;
    PK: geohash (6-character, ~1.2km² cell)&lt;br&gt;
    SK: timestamp_id (ISO8601#uuid)&lt;br&gt;
    GSI: city_id-time (for city-level queries)&lt;br&gt;
    TTL: 90 days automatic expiry&lt;br&gt;
The partition key choice is the most important decision in the whole architecture. I'm using geohash — a system that encodes latitude and longitude into a short string where nearby locations share a common prefix. A 6-character geohash represents roughly a 1.2km² cell, which maps naturally to what people think of as a neighborhood block.&lt;br&gt;
This means DynamoDB queries for "all reports in this area" hit a single partition. No expensive table scans. No scatter-gather across the whole dataset. The spatial query is essentially free at scale.&lt;br&gt;
Here's what the DynamoDB table looks like in production with real seeded data:&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqevvmtrdx3s7fd41k9c2.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqevvmtrdx3s7fd41k9c2.png" alt=" " width="799" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The scoring engine reads from DynamoDB, calculates neighborhood health scores using recency-weighted severity, and writes results to Aurora:&lt;br&gt;
GET /api/neighborhood/[geohash]&lt;br&gt;
    │&lt;br&gt;
    ├──► DynamoDB: fetch recent reports for this geohash&lt;br&gt;
    │&lt;br&gt;
    ├──► Scoring engine:&lt;br&gt;
    │    safetyScore = 100 - Σ(severity × recencyWeight × 3)&lt;br&gt;
    │    vibeScore   = 50  + Σ(severity × recencyWeight × 2)&lt;br&gt;
    │    recencyWeight: 1.0 (today) → 0.7 (week) → 0.4 (2 weeks) → 0.2 (month)&lt;br&gt;
    │&lt;br&gt;
    └──► Aurora PostgreSQL: persist neighborhood_scores row&lt;br&gt;
Aurora handles everything relational:&lt;br&gt;
sqlCREATE TABLE neighborhood_scores (&lt;br&gt;
  geohash_4            VARCHAR(4),&lt;br&gt;
  safety_score         DECIMAL(4,1),&lt;br&gt;
  vibe_score           DECIMAL(4,1),&lt;br&gt;
  infrastructure_score DECIMAL(4,1),&lt;br&gt;
  opportunity_score    DECIMAL(4,1),&lt;br&gt;
  overall_score        DECIMAL(4,1),&lt;br&gt;
  report_count_7d      INTEGER,&lt;br&gt;
  calculated_at        TIMESTAMPTZ DEFAULT NOW()&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;CREATE TABLE api_subscriptions (&lt;br&gt;
  id                     UUID PRIMARY KEY DEFAULT gen_random_uuid(),&lt;br&gt;
  user_id                UUID REFERENCES users(id),&lt;br&gt;
  plan_type              VARCHAR(20),&lt;br&gt;
  api_key                VARCHAR(64) UNIQUE,&lt;br&gt;
  calls_this_month       INTEGER DEFAULT 0,&lt;br&gt;
  monthly_calls_limit    INTEGER DEFAULT 10000,&lt;br&gt;
  stripe_subscription_id VARCHAR(100)&lt;br&gt;
);&lt;br&gt;
Here's the Aurora cluster running in production:&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmy66sxzp5oka2e84rt3f.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmy66sxzp5oka2e84rt3f.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What each database handles in production&lt;br&gt;
DynamoDB — stratum-reports:&lt;/p&gt;

&lt;p&gt;Every anonymous report write (millisecond latency globally)&lt;br&gt;
Map cluster reads (geohash-partitioned, zero cross-partition scans)&lt;br&gt;
Automatic TTL expiry on old reports after 90 days&lt;br&gt;
Zero ops: no connections to manage, no schema to migrate, no patching&lt;/p&gt;

&lt;p&gt;Aurora PostgreSQL — stratum-db:&lt;/p&gt;

&lt;p&gt;Neighborhood scores (persisted, queryable, comparable over time)&lt;br&gt;
User accounts and authentication state&lt;br&gt;
API subscription management and rate limiting&lt;br&gt;
Usage logging for billing&lt;br&gt;
Analytics exports for B2B customers&lt;br&gt;
Complex trend queries: safety score change week-over-week by city&lt;/p&gt;

&lt;p&gt;The mistake I almost made&lt;br&gt;
Halfway through building this, I had a moment of doubt. The dual-database setup felt like complexity I'd introduced unnecessarily. Two sets of credentials. Two connection clients. Two mental models to hold at once.&lt;br&gt;
I almost collapsed everything into Aurora.&lt;br&gt;
What stopped me was actually benchmarking the write path. Report submission endpoint with DynamoDB: consistently under 80ms end-to-end from Vercel edge to DynamoDB and back. With Aurora Serverless on a cold start: over 800ms.&lt;br&gt;
For a "tap to report" mobile interaction, that difference is everything. 80ms feels instant. 800ms feels broken.&lt;br&gt;
The complexity of two databases is real. But so is the performance cost of using the wrong one.&lt;/p&gt;

&lt;p&gt;When you should do this&lt;br&gt;
This architecture makes sense when your application has a clear write-heavy operational flow AND a separate analytical or relational layer.&lt;br&gt;
Use DynamoDB when:&lt;/p&gt;

&lt;p&gt;You have high-volume writes with simple, known structure&lt;br&gt;
Data is naturally partitioned by a key (user ID, location, device ID)&lt;br&gt;
Latency requirements are strict globally&lt;br&gt;
Data has a natural expiry (sessions, events, signals, logs)&lt;/p&gt;

&lt;p&gt;Use Aurora PostgreSQL when:&lt;/p&gt;

&lt;p&gt;You need complex queries across many records&lt;br&gt;
You have relational data that needs integrity constraints&lt;br&gt;
You're building billing, subscriptions, or any financial logic&lt;br&gt;
You need aggregations, trends, and data exports&lt;/p&gt;

&lt;p&gt;If your application has both — and many real applications do — don't choose. Use both. The operational cost is lower than you think, and the performance difference is not.&lt;/p&gt;

&lt;p&gt;The full architecture:&lt;/p&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7yzkndkv0avot515b5f.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe7yzkndkv0avot515b5f.png" alt=" " width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key insight: CQRS-style split. DynamoDB absorbs anonymous writes. Aurora serves durable analytics. Vercel connects them through serverless API routes. Each layer does exactly one job.&lt;/p&gt;

&lt;p&gt;Try it live&lt;br&gt;
STRATUM is live at &lt;a href="https://stratum-rho-green.vercel.app" rel="noopener noreferrer"&gt;https://stratum-rho-green.vercel.app&lt;/a&gt; with real data across three cities — San Francisco, Brooklyn, and Austin. The DynamoDB table holds 2,300+ real reports. Aurora holds the scoring and subscription layer.&lt;br&gt;
Open the map, click any cluster, and the neighborhood score card pulls live data from both databases in a single request.&lt;br&gt;
Demo login: &lt;a href="mailto:demo@stratum.app"&gt;demo@stratum.app&lt;/a&gt; / stratum2026&lt;br&gt;
I'm publishing this post as my official content submission for the H0: Hack the Zero Stack with Vercel v0 and AWS Databases hackathon.&lt;/p&gt;

&lt;p&gt;I created this project for the H0: Hack the Zero Stack with Vercel v0 and AWS Databases hackathon.&lt;/p&gt;

&lt;h1&gt;
  
  
  H0Hackathon
&lt;/h1&gt;

&lt;p&gt;Stack: Next.js 14 · Vercel · AWS DynamoDB · AWS Aurora PostgreSQL 17 · MapLibre GL JS · NextAuth · Stripe&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>aws</category>
      <category>showdev</category>
      <category>postgressql</category>
    </item>
  </channel>
</rss>
