<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Vinayak&#39;s Blog</title>
    <link>https://vinayakg.netlify.app/</link>
    <description>Recent content on Vinayak&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 18 May 2026 00:00:00 +0530</lastBuildDate>
    <atom:link href="https://vinayakg.netlify.app/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Why we replaced Kafka transactions with an adapter pattern</title>
      <link>https://vinayakg.netlify.app/posts/kafka-transactions-vs-adapter-pattern/</link>
      <pubDate>Mon, 18 May 2026 00:00:00 +0530</pubDate>
      <guid>https://vinayakg.netlify.app/posts/kafka-transactions-vs-adapter-pattern/</guid>
      <description>&lt;p&gt;A few weeks into running the new platform under production-like load, reconciliation started getting stuck. The audit service would tally up the day&amp;rsquo;s messages for a tenant, find its count short by a handful, and refuse to close out the batch. We&amp;rsquo;d dig in, find that one of the upstream services had published a message to its downstream topic but not to the audit topic, patch it up by hand, and watch the same thing happen on a different tenant the next day.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Solving the Dual Write Problem: Transactional Outbox Pattern with Debezium and MongoDB</title>
      <link>https://vinayakg.netlify.app/posts/dual-write-transactional-outbox/</link>
      <pubDate>Wed, 06 May 2026 00:00:00 +0530</pubDate>
      <guid>https://vinayakg.netlify.app/posts/dual-write-transactional-outbox/</guid>
      <description>&lt;p&gt;We run a platform where multiple services write to MongoDB and publish events to Kafka. Around 20 million messages flow through it every day. We needed both writes, the database state and the Kafka event, to either both succeed or both fail. The naive approach is two writes in application code, but no combination of try/catch, transactions, or retries across two systems solves that reliably. The failure window always exists: one write succeeds, the other doesn&amp;rsquo;t, and the system is silently inconsistent. This is the dual write problem.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How a misconfigured Kafka cleanup policy caused silent audit data loss</title>
      <link>https://vinayakg.netlify.app/posts/kafka-compact-issue/</link>
      <pubDate>Sat, 25 Apr 2026 00:00:00 +0530</pubDate>
      <guid>https://vinayakg.netlify.app/posts/kafka-compact-issue/</guid>
      <description>&lt;p&gt;During a performance test, we noticed that audit events for some messages were silently missing from MongoDB. No errors in the consumer logs, nothing in the DLT topic, and the producing services showed no errors. The audit service had consumed them. So why weren&amp;rsquo;t they in the database?&lt;/p&gt;&#xA;&lt;p&gt;The answer turned out to be a one-line config change we had made weeks earlier. And it had nothing to do with the audit service itself.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MongoDB Replace vs Update ($set): What Shows Up in the Oplog Might Surprise You</title>
      <link>https://vinayakg.netlify.app/posts/mongodb-replace-vs-set-oplog/</link>
      <pubDate>Sun, 29 Mar 2026 00:00:00 +0530</pubDate>
      <guid>https://vinayakg.netlify.app/posts/mongodb-replace-vs-set-oplog/</guid>
      <description>&lt;p&gt;If you&amp;rsquo;ve ever tailed MongoDB&amp;rsquo;s oplog or worked with Change Streams, you&amp;rsquo;ve probably run into a subtle but important difference between &lt;strong&gt;replace&lt;/strong&gt; and &lt;strong&gt;update ($set)&lt;/strong&gt; operations. The way MongoDB records these two in the oplog is fundamentally different — and it can bite you if you&amp;rsquo;re building anything downstream that depends on the full document.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Key takeaway:&lt;/strong&gt; MongoDB oplog entries for &lt;code&gt;replaceOne&lt;/code&gt; contain the full document, while &lt;code&gt;updateOne&lt;/code&gt; with &lt;code&gt;$set&lt;/code&gt; only records a diff — and that difference directly impacts downstream systems like CDC pipelines, change streams, and event-driven architectures.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
