<?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: Sai kirishna</title>
    <description>The latest articles on DEV Community by Sai kirishna (@krish2792).</description>
    <link>https://dev.to/krish2792</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%2F3970420%2Fbc1cdda8-231f-4ce1-9dde-31fc734dded4.png</url>
      <title>DEV Community: Sai kirishna</title>
      <link>https://dev.to/krish2792</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krish2792"/>
    <language>en</language>
    <item>
      <title>Your API Timed Out. Did the Order Still Go Through?</title>
      <dc:creator>Sai kirishna</dc:creator>
      <pubDate>Sat, 03 Oct 2026 19:24:00 +0000</pubDate>
      <link>https://dev.to/krish2792/your-api-timed-out-did-the-order-still-go-through-2j3n</link>
      <guid>https://dev.to/krish2792/your-api-timed-out-did-the-order-still-go-through-2j3n</guid>
      <description>&lt;p&gt;A customer clicks &lt;strong&gt;Place Order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The spinner turns… and turns… then: &lt;strong&gt;Request timed out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So they click again.&lt;/p&gt;

&lt;p&gt;Now you have two orders, two charges, and one angry support ticket.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable truth: &lt;strong&gt;a timeout tells you nothing about whether the server did the work.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;A timeout means &lt;em&gt;"no answer,"&lt;/em&gt; not &lt;em&gt;"no order."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Give every operation an &lt;strong&gt;idempotency key&lt;/strong&gt;: created once by the client, reused on every retry.&lt;/li&gt;
&lt;li&gt;Let a &lt;strong&gt;database unique constraint&lt;/strong&gt; decide which attempt wins, not an &lt;code&gt;if&lt;/code&gt; check.&lt;/li&gt;
&lt;li&gt;Save the order and its response &lt;strong&gt;in the same write&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A retry with a known key gets the &lt;strong&gt;original response back&lt;/strong&gt; instead of creating a new order.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client                     Server                    Database
  │                           │                          │
  │── POST /orders ──────────►│                          │
  │                           │── INSERT order ─────────►│  ✅ committed
  │      ✖ connection drops ◄─│── 201 Created            │
  │                           │                          │
  │  "Request timed out"      │                          │
  │                           │                          │
  │── POST /orders (retry) ──►│                          │
  │                           │── INSERT order ─────────►│  ✅ committed AGAIN 😬
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server did its job. Only the &lt;em&gt;response&lt;/em&gt; got lost.&lt;/p&gt;

&lt;p&gt;From the client's side, a timeout could mean any of three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The request never reached the server.&lt;/li&gt;
&lt;li&gt;The request reached the server and failed.&lt;/li&gt;
&lt;li&gt;The request &lt;strong&gt;succeeded&lt;/strong&gt;, but the response was lost.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The client can't tell which one happened. So the backend has to be built so that &lt;strong&gt;retrying is always safe&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The fix in one sentence
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Give the operation an identity that stays the same across retries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of a paper check. If check &lt;strong&gt;#1042&lt;/strong&gt; shows up twice, the bank doesn't pay it twice. The check number identifies the &lt;em&gt;intent to pay&lt;/em&gt;, no matter how many times it's presented.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;idempotency key&lt;/strong&gt; is the check number for your API request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: The client creates the key once
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Create the key ONCE, when the customer decides to place this order.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pendingOrder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;KEYBOARD-01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&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;submitOrder&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/orders&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="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Idempotency-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pendingOrder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// same key on every retry&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pendingOrder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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;strong&gt;The most common bug:&lt;/strong&gt; generating the key &lt;em&gt;inside&lt;/em&gt; &lt;code&gt;submitOrder()&lt;/code&gt;. Then every retry gets a new key and looks like a brand-new order, which defeats the whole point.&lt;/p&gt;

&lt;p&gt;If retries need to survive a page reload or app restart, persist the pending operation and its key somewhere durable. A variable in memory disappears when the page does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just detect duplicate request bodies?
&lt;/h3&gt;

&lt;p&gt;Because identical requests don't always mean identical &lt;em&gt;intent&lt;/em&gt;. A customer might genuinely want to order the same keyboard twice. The &lt;a href="https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/" rel="noopener noreferrer"&gt;Amazon Builders' Library&lt;/a&gt; makes this point: the caller has to say which attempts belong together.&lt;/p&gt;

&lt;h3&gt;
  
  
  The API contract
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New key&lt;/td&gt;
&lt;td&gt;Create the order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same customer, same key, same input&lt;/td&gt;
&lt;td&gt;Return the &lt;strong&gt;original&lt;/strong&gt; response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same customer, same key, different input&lt;/td&gt;
&lt;td&gt;&lt;code&gt;409 Conflict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Different customer, same key&lt;/td&gt;
&lt;td&gt;Treat as a separate operation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;🔐 Authenticate and authorize &lt;strong&gt;every&lt;/strong&gt; attempt, including replays. An idempotency key is not a credential.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Save the order and the replay record together
&lt;/h2&gt;

&lt;p&gt;This looks reasonable, but it's broken:&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&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;saveIdempotencyResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 💥 crash here = no record&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the process crashes between those two lines, the order exists but nothing remembers the key. The next retry creates a second order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The order and the record of the key must commit together, or not at all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simplest way is to keep them in the same row:&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;orders&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="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;customer_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;idempotency_key&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="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;request_payload&lt;/span&gt;   &lt;span class="n"&gt;JSONB&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;creation_response&lt;/span&gt; &lt;span class="n"&gt;JSONB&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;created_at&lt;/span&gt;        &lt;span class="n"&gt;TIMESTAMPTZ&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="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

  &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&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;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;UNIQUE&lt;/code&gt; constraint is what makes everything else work.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(This table serves only the create-order operation. If you build a shared idempotency table, add an operation name to the unique key.)&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Let the database pick the winner
&lt;/h2&gt;

&lt;p&gt;The obvious approach fails under concurrency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request A: SELECT key → not found
Request B: SELECT key → not found
Request A: INSERT order ✅
Request B: INSERT order ✅   ← duplicate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking first and then inserting leaves a gap that two requests can both slip through. Instead, &lt;strong&gt;just try the insert&lt;/strong&gt; and let PostgreSQL's unique constraint decide which one wins.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;randomUUID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Pool&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pg&lt;/span&gt;&lt;span class="dl"&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;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Pool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;OrderInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;sku&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="nl"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CreationResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&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="nl"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accepted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Inputs are already validated; customerId comes from the authenticated user.&lt;/span&gt;
&lt;span class="k"&gt;export&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;createOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;customerId&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;key&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;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;OrderInput&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="c1"&gt;// Include every field that changes what the operation does.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&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;orderId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&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;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreationResponse&lt;/span&gt; &lt;span class="o"&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;accepted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Try to create the order. The unique constraint blocks duplicates.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inserted&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;creation_response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreationResponse&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="s2"&gt;`INSERT INTO orders (
       id, customer_id, idempotency_key, request_payload, creation_response
     )
     VALUES ($1, $2, $3, $4::jsonb, $5::jsonb)
     ON CONFLICT (customer_id, idempotency_key) DO NOTHING
     RETURNING creation_response`&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;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. We won: this is a brand-new order.&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;inserted&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="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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;inserted&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;creation_response&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. The key already exists. Look up what happened the first time.&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existing&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;same_request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;creation_response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreationResponse&lt;/span&gt;&lt;span class="p"&gt;;&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="s2"&gt;`SELECT request_payload = $3::jsonb AS same_request, creation_response
     FROM orders
     WHERE customer_id = $1 AND idempotency_key = $2`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&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;previous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;existing&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="mi"&gt;0&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Never silently fall through to creating a second order.&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="s2"&gt;Idempotency record unavailable&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="c1"&gt;// 4. Same key, different request: the client made a mistake.&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;same_request&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;409&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Key already used with different input&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="c1"&gt;// 5. A true retry: return the original result.&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;creation_response&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;h3&gt;
  
  
  What this code does, in plain English
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Try to insert.&lt;/strong&gt; The unique constraint guarantees at most one row per customer and key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inserted?&lt;/strong&gt; It's a new order, so return &lt;code&gt;201&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not inserted?&lt;/strong&gt; Someone already used this key, so read what they stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different payload?&lt;/strong&gt; Return &lt;code&gt;409&lt;/code&gt;. The key was reused for a different request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Same payload?&lt;/strong&gt; Return the original response. The customer sees the same order ID as the first time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;💡 Many APIs also add a response header such as &lt;code&gt;Idempotent-Replayed: true&lt;/code&gt; so clients can tell a replay from a fresh creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why the separate &lt;code&gt;SELECT&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Under PostgreSQL's default &lt;code&gt;READ COMMITTED&lt;/code&gt; isolation, &lt;code&gt;ON CONFLICT DO NOTHING&lt;/code&gt; can be blocked by a row that the &lt;code&gt;INSERT&lt;/code&gt; statement itself can't see. A new statement takes a fresh snapshot, so it can see that row. The &lt;a href="https://www.postgresql.org/docs/current/transaction-iso.html" rel="noopener noreferrer"&gt;PostgreSQL docs&lt;/a&gt; explain the details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing to more than one table?
&lt;/h3&gt;

&lt;p&gt;Wrap all the related writes in one explicit transaction. With &lt;code&gt;node-postgres&lt;/code&gt;, every statement in that transaction must use the &lt;strong&gt;same checked-out client&lt;/strong&gt; from the pool, not &lt;code&gt;pool.query()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also set bounded database timeouts. A request waiting on a competing request shouldn't hold resources forever.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this guarantees, and what it doesn't
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Guaranteed:&lt;/strong&gt; for a given customer and key, &lt;strong&gt;at most one order is created&lt;/strong&gt;, for as long as the key is stored.&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Not guaranteed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;that the customer received the response&lt;/li&gt;
&lt;li&gt;that payment succeeded&lt;/li&gt;
&lt;li&gt;that inventory was reserved&lt;/li&gt;
&lt;li&gt;that a confirmation email was sent&lt;/li&gt;
&lt;li&gt;that two &lt;em&gt;different&lt;/em&gt; keys really represent two different purchases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The replay returns the &lt;strong&gt;original creation response&lt;/strong&gt;. If the client needs the order's &lt;em&gt;current&lt;/em&gt; state, such as shipped or cancelled, that's a separate &lt;code&gt;GET /orders/:id&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Side effects outside your database
&lt;/h2&gt;

&lt;p&gt;A PostgreSQL transaction can't include an HTTP call to a payment provider. If you charge the card and then crash, the database doesn't know about the charge.&lt;/p&gt;

&lt;p&gt;A common fix is the &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html" rel="noopener noreferrer"&gt;transactional outbox pattern&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌───────── one DB transaction ─────────┐
│  INSERT order                        │
│  INSERT outbox_event (charge card)   │
└──────────────────────────────────────┘
                  │
                  ▼
        Worker reads outbox → calls provider → retries on failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The worker may deliver an event more than once, so consumers must deduplicate too. It's idempotency all the way down.&lt;/p&gt;

&lt;p&gt;For payments, use the provider's own idempotency mechanism with a stable payment-operation ID. If the provider call times out, check the payment's status or reconcile it before trying again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Keys that expire change the guarantee
&lt;/h2&gt;

&lt;p&gt;The example above keeps keys forever. If you move them into a separate table and delete old ones, a very late retry will look brand new.&lt;/p&gt;

&lt;p&gt;Stripe, for example, documents that keys may be removed once they're at least 24 hours old. That's Stripe's contract, not a universal rule.&lt;/p&gt;

&lt;p&gt;Rule of thumb: &lt;strong&gt;keep keys at least as long as your longest realistic retry window.&lt;/strong&gt; If the business needs permanent uniqueness, enforce a durable business ID, such as a checkout ID, separately from the expiring key store.&lt;/p&gt;




&lt;h2&gt;
  
  
  Test the scary cases
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Expected result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Two simultaneous requests, same key&lt;/td&gt;
&lt;td&gt;One order; both get the same successful response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same key, changed quantity&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;409&lt;/code&gt;; original order unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB commits, HTTP response is lost&lt;/td&gt;
&lt;td&gt;Retry returns the &lt;strong&gt;original&lt;/strong&gt; order ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert rolls back before commit&lt;/td&gt;
&lt;td&gt;Retry creates the order normally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client restarts before retrying&lt;/td&gt;
&lt;td&gt;Persisted key is reused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key expired (if you clean up)&lt;/td&gt;
&lt;td&gt;Behavior matches your documented retention&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The most revealing test is the lost response:&lt;/strong&gt; let the database commit, kill the connection before the response arrives, then retry. If you get a second order, you have a bug that's waiting for production traffic to find it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Key generated &lt;strong&gt;once&lt;/strong&gt; per operation and reused on every retry&lt;/li&gt;
&lt;li&gt;✅ Key persisted if retries must survive a reload or restart&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;UNIQUE (customer_id, idempotency_key)&lt;/code&gt; enforced in the database&lt;/li&gt;
&lt;li&gt;✅ Business write and replay response committed &lt;strong&gt;atomically&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ Same key with different input returns &lt;code&gt;409&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Auth checked on &lt;strong&gt;every&lt;/strong&gt; attempt, including replays&lt;/li&gt;
&lt;li&gt;✅ External side effects go through an outbox with idempotent consumers&lt;/li&gt;
&lt;li&gt;✅ Key retention covers your real retry window&lt;/li&gt;
&lt;li&gt;✅ Lost-response case covered by a test&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;A timeout is a question, not an answer. Your API should be able to answer it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When a client can't tell whether its first attempt succeeded, can your API safely return the original result?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;How does your team handle retries today? Let me know in the comments. 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>postgres</category>
      <category>typescript</category>
      <category>ai</category>
    </item>
    <item>
      <title>Give Claude Desktop Persistent Memory in 3 Minutes</title>
      <dc:creator>Sai kirishna</dc:creator>
      <pubDate>Fri, 05 Jun 2026 20:41:47 +0000</pubDate>
      <link>https://dev.to/krish2792/give-claude-desktop-persistent-memory-in-3-minutes-5a0j</link>
      <guid>https://dev.to/krish2792/give-claude-desktop-persistent-memory-in-3-minutes-5a0j</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Claude Desktop is incredibly capable.&lt;/p&gt;

&lt;p&gt;But it has one major limitation:&lt;/p&gt;

&lt;p&gt;Every new conversation starts with a blank slate.&lt;/p&gt;

&lt;p&gt;Your preferences?&lt;/p&gt;

&lt;p&gt;Gone.&lt;/p&gt;

&lt;p&gt;Your architecture decisions?&lt;/p&gt;

&lt;p&gt;Gone.&lt;/p&gt;

&lt;p&gt;Your project context?&lt;/p&gt;

&lt;p&gt;Gone.&lt;/p&gt;

&lt;p&gt;Your engineering philosophy?&lt;/p&gt;

&lt;p&gt;Gone.&lt;/p&gt;

&lt;p&gt;For example, you tell Claude:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I prefer Zustand over Redux because I value minimal boilerplate and lightweight state management."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next day, in a new session, Claude might recommend Redux Toolkit.&lt;/p&gt;

&lt;p&gt;Not because it made a bad decision.&lt;/p&gt;

&lt;p&gt;Because it has no memory of your previous reasoning.&lt;/p&gt;

&lt;p&gt;As a result, developers spend time re-explaining the same context over and over again.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Breeth + MCP
&lt;/h2&gt;

&lt;p&gt;Breeth adds persistent memory to Claude Desktop through the Model Context Protocol (MCP).&lt;/p&gt;

&lt;p&gt;Unlike traditional memory systems that store only facts, Breeth stores the reasoning behind those facts.&lt;/p&gt;

&lt;p&gt;Every memory can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;why_connected&lt;/strong&gt; → Why this fact matters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;director_vision&lt;/strong&gt; → The larger goal it supports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;cognitive_pattern&lt;/strong&gt; → The user's decision-making style&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows Claude to understand not only what you prefer, but why you prefer it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Get Your API Key
&lt;/h2&gt;

&lt;p&gt;Create a free account at:&lt;/p&gt;

&lt;p&gt;thebreeth.com&lt;/p&gt;

&lt;p&gt;After signing up, generate an API key from the dashboard.&lt;/p&gt;

&lt;p&gt;You'll use this key to connect Claude Desktop to Breeth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Configure Claude Desktop
&lt;/h2&gt;

&lt;p&gt;Open your Claude Desktop configuration file.&lt;/p&gt;

&lt;h3&gt;
  
  
  macOS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;~/Library/Application Support/Claude/claude_desktop_config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Windows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;%APPDATA%/Claude/claude_desktop_config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following MCP server configuration:&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;"mcpServers"&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;"breeth"&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;"type"&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"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.thebreeth.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"headers"&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;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer YOUR_API_KEY_HERE"&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="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;Replace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YOUR_API_KEY_HERE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with your actual Breeth API key.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Restart Claude Desktop
&lt;/h2&gt;

&lt;p&gt;Save the configuration file.&lt;/p&gt;

&lt;p&gt;Restart Claude Desktop.&lt;/p&gt;

&lt;p&gt;Once Claude launches, the Breeth MCP tools will automatically become available.&lt;/p&gt;

&lt;p&gt;Setup complete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Tell Claude something meaningful:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I always choose Zustand over Redux because I dislike boilerplate. Keep this preference in mind for future architecture decisions."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Breeth stores the preference together with its reasoning.&lt;/p&gt;

&lt;p&gt;Now start a completely new Claude session.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Help me choose state management for a React dashboard."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of starting from scratch, Claude can retrieve your stored reasoning and make recommendations aligned with your engineering preferences.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Gets Stored?
&lt;/h2&gt;

&lt;p&gt;Breeth stores memories with intent metadata.&lt;/p&gt;

&lt;p&gt;Example:&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;"fact"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User prefers Zustand over Redux"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"intent_meta"&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;"why_connected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User values minimal boilerplate and clean syntax"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"director_vision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Build lightweight maintainable frontend architecture"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cognitive_pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"minimalism-first engineering"&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;This creates a reusable reasoning framework rather than a collection of disconnected facts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Most memory systems answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What did the user say?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Breeth attempts to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why did the user say it?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction becomes increasingly important as AI agents begin making architectural, design, and implementation decisions on your behalf.&lt;/p&gt;

&lt;p&gt;Remembering facts is useful.&lt;/p&gt;

&lt;p&gt;Remembering principles is far more powerful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Free Tier
&lt;/h2&gt;

&lt;p&gt;Breeth is free to get started.&lt;/p&gt;

&lt;p&gt;No credit card required.&lt;/p&gt;

&lt;p&gt;Sign up at:&lt;/p&gt;

&lt;p&gt;thebreeth.com&lt;/p&gt;

&lt;p&gt;Use promo code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PU3-100&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;to receive 3 months free on the Starter plan.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;In the next article, we'll put Breeth head-to-head against Mem0 in a real multi-agent benchmark.&lt;/p&gt;

&lt;p&gt;We'll examine how flat vector memory compares to intent-aware memory when agents must make architectural decisions based on user preferences.&lt;/p&gt;

&lt;p&gt;The results were more interesting than expected.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>agents</category>
      <category>memory</category>
    </item>
  </channel>
</rss>
