<?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: Mandar Gokhale</title>
    <description>The latest articles on DEV Community by Mandar Gokhale (@mandarg13).</description>
    <link>https://dev.to/mandarg13</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%2F339271%2F3c8017b0-ad0a-44fd-8b40-c9995c86ef13.jpg</url>
      <title>DEV Community: Mandar Gokhale</title>
      <link>https://dev.to/mandarg13</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mandarg13"/>
    <language>en</language>
    <item>
      <title>Helping a friend connect his BigRock domain to Cloudflare pages</title>
      <dc:creator>Mandar Gokhale</dc:creator>
      <pubDate>Fri, 22 Aug 2025 18:48:48 +0000</pubDate>
      <link>https://dev.to/mandarg13/helping-a-friend-connect-his-bigrock-domain-to-cloudflare-pages-912</link>
      <guid>https://dev.to/mandarg13/helping-a-friend-connect-his-bigrock-domain-to-cloudflare-pages-912</guid>
      <description>&lt;p&gt;A friend of mine needed a simple one-page website for his business. Nothing fancy — just something professional that could go live quickly. I figured &lt;strong&gt;Cloudflare Pages&lt;/strong&gt; was the best option: free hosting, blazing-fast CDN, and automatic SSL.&lt;/p&gt;

&lt;p&gt;I knew the basics: if I could point the domain from &lt;strong&gt;BigRock&lt;/strong&gt; to Cloudflare using CNAMEs, we’d be in business. At least, that’s what I thought.&lt;/p&gt;




&lt;h2&gt;
  
  
  BigRock’s Old vs New UI Problem
&lt;/h2&gt;

&lt;p&gt;The first hurdle was &lt;strong&gt;BigRock’s interface&lt;/strong&gt;. They have an “old” UI and a “new” UI — and they don’t behave the same way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the &lt;strong&gt;old UI&lt;/strong&gt;, I could actually delete BigRock’s default nameservers and replace them with Cloudflare’s nameservers (as required).&lt;/li&gt;
&lt;li&gt;In the &lt;strong&gt;new UI&lt;/strong&gt;, the old nameservers kept showing alongside the new ones, which was confusing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you’re stuck, pro tip: &lt;strong&gt;use the old BigRock UI to make clean changes to nameservers&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Domain Mapping and CNAME Setup
&lt;/h2&gt;

&lt;p&gt;Once the domain was delegated to Cloudflare, the next step was setting up DNS records inside Cloudflare. This is where the &lt;strong&gt;domain mapping&lt;/strong&gt; happens — it’s how your friendly business domain (&lt;code&gt;example.com&lt;/code&gt;) gets connected to the special &lt;code&gt;.pages.dev&lt;/code&gt; address Cloudflare Pages gives you.&lt;/p&gt;

&lt;p&gt;The correct setup looks like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Target (Content)&lt;/th&gt;
&lt;th&gt;Proxy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;your-project&amp;gt;.pages.dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Proxied (orange cloud)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CNAME&lt;/td&gt;
&lt;td&gt;&lt;code&gt;www&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;your-project&amp;gt;.pages.dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Proxied (orange cloud)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@&lt;/code&gt; represents the root domain (example.com).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;www&lt;/code&gt; is the subdomain (&lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Both must point to the Cloudflare Pages project’s &lt;code&gt;.pages.dev&lt;/code&gt; domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This part I got right — but the site still wouldn’t load.&lt;/p&gt;




&lt;h2&gt;
  
  
  Debugging with &lt;code&gt;dig&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;After switching nameservers and adding CNAMEs, I expected things to work right away. But no — the website kept throwing &lt;strong&gt;gateway timeouts&lt;/strong&gt; and later &lt;strong&gt;522 errors&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s when the &lt;code&gt;dig&lt;/code&gt; command became my best friend:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig www.example.com CNAME
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command showed me whether the DNS records were actually resolving. For a long time, &lt;code&gt;dig&lt;/code&gt; returned &lt;strong&gt;nothing&lt;/strong&gt;, which told me the changes hadn’t propagated or weren’t set correctly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Missing Piece: Custom Domains in Cloudflare Pages
&lt;/h2&gt;

&lt;p&gt;Here’s the part that tripped me up the most.&lt;/p&gt;

&lt;p&gt;Even though I had the CNAME records pointing correctly, I didn’t realize that Cloudflare Pages also requires you to register the domain inside the project itself.&lt;/p&gt;

&lt;p&gt;To fix this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Cloudflare → Workers &amp;amp; Pages → Your Pages Project → Custom Domains&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add both the root domain (&lt;code&gt;example.com&lt;/code&gt;) and the &lt;code&gt;www&lt;/code&gt; domain (&lt;code&gt;www.example.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Cloudflare then validates the DNS setup and issues SSL certificates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until you do this, you’ll keep getting &lt;strong&gt;522 errors&lt;/strong&gt;, because Pages doesn’t yet know the domain belongs to your project.&lt;/p&gt;




&lt;h2&gt;
  
  
  SSL and the Final Wait
&lt;/h2&gt;

&lt;p&gt;Once I finally added the custom domains in Cloudflare Pages, everything clicked into place. DNS validated, Cloudflare started issuing SSL, and after 10–30 minutes the status showed &lt;strong&gt;Active&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My friend’s one-page site was finally live on his BigRock domain — fast, secure, and free.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;BigRock UI quirks:&lt;/strong&gt; sometimes only the old UI lets you remove their default nameservers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CNAMEs are essential:&lt;/strong&gt; you must map both root and &lt;code&gt;www&lt;/code&gt; to your Pages project’s &lt;code&gt;.pages.dev&lt;/code&gt; domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dig&lt;/code&gt; is your friend:&lt;/strong&gt; it confirms if DNS is actually resolving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Domains in Pages are required:&lt;/strong&gt; DNS records alone are not enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL takes time:&lt;/strong&gt; don’t panic if you see errors while it’s still provisioning.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Common Errors &amp;amp; Fixes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gateway Timeout (504 / 522)&lt;/strong&gt; → Usually means your CNAME records are missing or incorrect. Make sure both root and &lt;code&gt;www&lt;/code&gt; point to your Pages project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Error 522 after CNAMEs are correct&lt;/strong&gt; → You likely forgot to add the domain inside &lt;strong&gt;Cloudflare Pages → Custom Domains&lt;/strong&gt;. Add both root and &lt;code&gt;www&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SSL Pending or Invalid Certificate&lt;/strong&gt; → Normal after adding a custom domain. Wait 10–30 minutes; Cloudflare will provision SSL automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Old Nameservers Still Showing&lt;/strong&gt; → Use BigRock’s old UI to delete default nameservers, and wait for propagation (24–48 hours). Confirm with &lt;code&gt;dig&lt;/code&gt; or &lt;a href="https://dnschecker.org" rel="noopener noreferrer"&gt;dnschecker.org&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Site works on www but not root (or vice versa)&lt;/strong&gt; → Add a redirect rule in Cloudflare so one version forwards to the other (better for SEO).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I’ll Use Cloudflare Pages Again
&lt;/h2&gt;

&lt;p&gt;Despite the confusion, Cloudflare Pages is a fantastic platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No servers to manage.&lt;/li&gt;
&lt;li&gt;Free global CDN and SSL.&lt;/li&gt;
&lt;li&gt;Smooth Git integration for deployments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that I know the “gotchas” — BigRock’s UI quirks, CNAME domain mapping, and the hidden &lt;strong&gt;Custom Domains&lt;/strong&gt; step — the process is much smoother.&lt;/p&gt;

&lt;p&gt;And most importantly: my friend’s site is online, looking professional, and loading fast.&lt;/p&gt;

</description>
      <category>cloudflare</category>
      <category>dns</category>
      <category>serverless</category>
      <category>website</category>
    </item>
    <item>
      <title>Isolation — The Trickiest ACID Pillar (And Why It Matters More Than You Think)</title>
      <dc:creator>Mandar Gokhale</dc:creator>
      <pubDate>Sun, 25 May 2025 10:56:42 +0000</pubDate>
      <link>https://dev.to/mandarg13/isolation-the-trickiest-acid-pillar-and-why-it-matters-more-than-you-think-57bb</link>
      <guid>https://dev.to/mandarg13/isolation-the-trickiest-acid-pillar-and-why-it-matters-more-than-you-think-57bb</guid>
      <description>&lt;p&gt;When I first started diving into ACID properties, I thought I had them figured out. Atomicity? Sure, all-or-nothing makes sense. Consistency? Yeah, keep your data valid. Durability? Of course, don't lose my writes. But &lt;strong&gt;Isolation&lt;/strong&gt;? &lt;/p&gt;

&lt;p&gt;That one had me scratching my head.&lt;/p&gt;

&lt;p&gt;The textbook definition was simple enough:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Each transaction should run as if it's the only one in the system."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what does that &lt;em&gt;actually&lt;/em&gt; look like? I kept staring at this definition thinking, "Okay, but how do you even &lt;em&gt;see&lt;/em&gt; that happening?" I couldn't visualize it, so naturally, I went down a rabbit hole.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 The "Aha!" Moment: It's Not Black and White
&lt;/h2&gt;

&lt;p&gt;Here's what clicked for me: isolation isn't just "on" or "off." There's actually a whole &lt;strong&gt;spectrum&lt;/strong&gt; of isolation behaviors, and databases let you pick your poison through something called &lt;strong&gt;Isolation Levels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Picture this scenario that made it all clear for me:&lt;br&gt;
You're halfway through generating a payroll report. You've started reading employee salaries when—plot twist—someone else adds a brand new employee to the system.&lt;/p&gt;

&lt;p&gt;Will your report include that new person or not?&lt;/p&gt;

&lt;p&gt;My first instinct was "Well, it depends on timing, right?" But that's when I realized: &lt;strong&gt;It depends on the isolation level you choose.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's when it hit me—I wasn't just learning what isolation &lt;em&gt;was&lt;/em&gt;; I needed to understand all the different &lt;em&gt;flavors&lt;/em&gt; of isolation that databases actually offer. So I started exploring them one by one, and each level taught me something new about the trade-offs involved.&lt;/p&gt;


&lt;h2&gt;
  
  
  🗺️ &lt;strong&gt;My Tour Through the Isolation Levels&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let me walk you through how I understood each level—not through boring charts, but through the stories and examples that made them click for me. I'll start from the most relaxed level and work up to the strictest.&lt;/p&gt;
&lt;h3&gt;
  
  
  1️⃣ Read Uncommitted: "I'll Take Whatever You've Got" 📥
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Show me anything, even if it's not officially saved yet."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I first read about this level, my reaction was: &lt;em&gt;"Wait, you can read data that might disappear? That sounds insane!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This level lets you &lt;strong&gt;read data that other transactions haven't even committed yet&lt;/strong&gt;. So you might read something that gets rolled back moments later. These are called &lt;strong&gt;dirty reads&lt;/strong&gt;, and they sound as messy as they are.&lt;/p&gt;

&lt;p&gt;Here's what freaked me out initially:&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="c1"&gt;-- Transaction A starts transferring money&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Alice's balance is now -500, but not committed yet&lt;/span&gt;

&lt;span class="c1"&gt;-- Transaction B peeks at the data&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Reads -500, even though A might roll back!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first thought: "Who would ever want this madness?"&lt;/p&gt;

&lt;p&gt;But then I found a use case that actually made sense. Imagine you're building a real-time dashboard showing server metrics. The numbers update every second, and you care more about seeing the &lt;strong&gt;latest trend&lt;/strong&gt; than getting every single digit perfect.&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;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cpu_usage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'5 minutes'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if some writes get rolled back, you just want the most current signal. You're trading &lt;strong&gt;accuracy for speed&lt;/strong&gt;—and sometimes that's exactly what you need.&lt;/p&gt;

&lt;p&gt;It's still risky as hell, but when used intentionally? It can be the right call.&lt;/p&gt;

&lt;h3&gt;
  
  
  2️⃣ &lt;strong&gt;Read Committed: The Sensible Default&lt;/strong&gt; ✅
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Only show me the official, committed stuff."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This one felt like the Goldilocks zone to me—not too loose, not too strict. It ensures you &lt;strong&gt;only see data that's been properly committed&lt;/strong&gt;. No more dirty reads, no more reading stuff that might vanish.&lt;/p&gt;

&lt;p&gt;That's why it's the &lt;strong&gt;default in PostgreSQL and MySQL&lt;/strong&gt;. It just makes sense for most situations.&lt;/p&gt;

&lt;p&gt;But here's where I got my next surprise:&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="c1"&gt;-- I start a transaction&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&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;balance&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Returns 1000&lt;/span&gt;

&lt;span class="c1"&gt;-- Meanwhile, someone else updates Alice's balance&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- I read again in the same transaction&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Now returns 4000. Wait, what?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though I avoided dirty reads, the data could still &lt;strong&gt;change between my reads&lt;/strong&gt;—this problem is called a &lt;strong&gt;non-repeatable read&lt;/strong&gt;. But Read Committed &lt;em&gt;also&lt;/em&gt; doesn't protect against another subtle issue I discovered: &lt;strong&gt;phantom reads&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  😵‍💫 Wait, What’s a Phantom Read?
&lt;/h3&gt;

&lt;p&gt;This concept had me confused for a while, so let me explain it the way it finally clicked for me:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phantom Read&lt;/strong&gt; = New rows magically "appear" when you repeat the same query within your transaction.&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="c1"&gt;-- I start looking at the sales team&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Results: Alice, Bob, Carol (3 people)&lt;/span&gt;

&lt;span class="c1"&gt;-- Meanwhile, HR adds someone new&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'David'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- I run the exact same query again&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;employees&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Sales'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="c1"&gt;-- Results: Alice, Bob, Carol, David (4 people)&lt;/span&gt;
&lt;span class="c1"&gt;-- David is the "phantom"—he wasn't there before!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's called "phantom" because these new rows appear like ghosts—they weren't there when you first looked, but suddenly materialize out of thin air.&lt;/p&gt;

&lt;p&gt;This got me thinking: when would this actually matter?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3️⃣ Repeatable Read: "I Want Consistency, Dammit!" 🔁&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Give me the same data every time I look."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Initially, I couldn't figure out when I'd need this. I mean, if I'm just grabbing payroll data for April 2025:&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;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;payroll&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;pay_month&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-04'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should give me consistent results, right? Why would I need something stronger?&lt;/p&gt;

&lt;p&gt;Then it hit me: &lt;strong&gt;this is about long-running transactions&lt;/strong&gt;. Not your quick 100ms queries, but operations that take &lt;strong&gt;minutes or hours&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  💡 The Lightbulb Moment: Audit Reports
&lt;/h4&gt;

&lt;p&gt;Imagine generating a regulatory audit report for all transactions on January 15th. This beast takes 30+ minutes and touches multiple tables:&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;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- Using Repeatable Read&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 1: Get summary totals&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;debit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-15'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;credit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-15'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 2: Count failures&lt;/span&gt;
&lt;span class="k"&gt;SELECT&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;FROM&lt;/span&gt; &lt;span class="n"&gt;failed_transactions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-15'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Step 3: Detailed breakdown (this takes forever)&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;account_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;transactions&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-01-15'&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;account_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If someone inserts a new transaction with the same date while I'm running this, my summary totals won't match my detailed breakdown. The whole report becomes garbage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repeatable Read saves the day&lt;/strong&gt; by giving me a consistent snapshot for the entire duration. No phantom reads, no surprises—just the same view of data from start to finish.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;👁️ Another Eye-Opener: Clinical Research&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here's another scenario that really drove the point home for me. Imagine you're analyzing data from a clinical trial—this stuff is serious, lives depend on getting it right:&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="c1"&gt;-- Clinical trial analysis - data consistency is critical&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blood_pressure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;treatment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'drug_a'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="k"&gt;AVG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;blood_pressure&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;patients&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;treatment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'placebo'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&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;FROM&lt;/span&gt; &lt;span class="n"&gt;adverse_events&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;treatment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'drug_a'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Multiple statistical calculations that take hours...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If patient data gets updated while you're crunching these numbers—maybe new test results come in, or adverse events get recorded—your statistical conclusions become completely invalid. You might conclude that Drug A is safer than it actually is, or vice versa.&lt;/p&gt;

&lt;p&gt;In research, &lt;strong&gt;temporal consistency isn't just nice to have—it's legally required&lt;/strong&gt;. Your analysis must be based on a single, coherent snapshot of the data, or regulatory bodies will throw it out.&lt;/p&gt;

&lt;p&gt;This is huge for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Financial audits&lt;/strong&gt; where numbers must add up perfectly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scientific research&lt;/strong&gt; where data consistency affects validity and regulatory approval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk analysis&lt;/strong&gt; where inconsistent snapshots lead to catastrophically bad decisions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most web apps don't need this level of protection, but when you do? There's absolutely no substitute.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4️⃣ Serializable: "No Funny Business Allowed" 🚫&lt;/strong&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Make it behave like transactions run one at a time, period."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the &lt;strong&gt;nuclear option&lt;/strong&gt;—the highest isolation level that guarantees transactions behave as if they ran sequentially, even though they're actually concurrent. &lt;/p&gt;

&lt;p&gt;I thought Repeatable Read was strict, but Serializable prevents an even more subtle problem that blew my mind: &lt;strong&gt;write skew&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  😷 The Hospital Shift Nightmare
&lt;/h4&gt;

&lt;p&gt;This example made write skew crystal clear for me. Imagine a hospital scheduling system with one critical rule: &lt;strong&gt;"At least one doctor must be on duty at all times."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Right now, there are exactly 2 doctors scheduled for tonight: Dr. Alice and Dr. Bob.&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="c1"&gt;-- Transaction A: Dr. Alice wants time off&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&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;FROM&lt;/span&gt; &lt;span class="n"&gt;shifts&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-05-25'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'night'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Returns: 2 doctors&lt;/span&gt;
&lt;span class="c1"&gt;-- Alice thinks: "2 - 1 = 1 remaining, I can take time off!"&lt;/span&gt;

&lt;span class="c1"&gt;-- Transaction B: Dr. Bob wants time off (running at the same time!)&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&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;FROM&lt;/span&gt; &lt;span class="n"&gt;shifts&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-05-25'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'night'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- Returns: 2 doctors  &lt;/span&gt;
&lt;span class="c1"&gt;-- Bob thinks: "2 - 1 = 1 remaining, I can take time off too!"&lt;/span&gt;

&lt;span class="c1"&gt;-- Both update different rows&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;shifts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'time_off'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;doctor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-05-25'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;shifts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'time_off'&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;doctor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'2025-05-25'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;COMMIT&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;Result&lt;/strong&gt;: Both doctors got approved for time off. The night shift now has &lt;strong&gt;zero doctors&lt;/strong&gt;. The hospital's critical rule just got violated!&lt;/p&gt;

&lt;p&gt;This is write skew—both transactions read the same data, made logical decisions, but their combined effect created chaos. Traditional row locking wouldn't catch this because they modified different rows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Serializable isolation&lt;/strong&gt; would detect this conflict and abort one transaction. When the unlucky doctor retries, they'd see only 1 doctor scheduled and get their request denied. Crisis averted.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;🦸‍♂️ When You Actually Need This Superpower&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Banking&lt;/strong&gt;: Preventing family accounts from going below minimum balances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Healthcare&lt;/strong&gt;: Ensuring minimum staff coverage (like our hospital example)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inventory&lt;/strong&gt;: Preventing overselling when stock is critically low&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any system&lt;/strong&gt; where business rules span multiple rows or tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off? Performance takes a hit because more transactions get aborted and retried. But when you need bulletproof consistency? It's the only game in town.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📚 What This Journey Taught Me&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Digging into isolation levels wasn't just about learning database theory—it completely changed how I think about concurrent systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolation is sneaky powerful&lt;/strong&gt;. Those subtle bugs that only happen under load? Often isolation issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different problems need different solutions&lt;/strong&gt;. There's no one-size-fits-all isolation level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Most importantly&lt;/strong&gt;: Just because your data is committed doesn't mean it's consistent from a business logic perspective.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you've ever wondered why building reliable concurrent systems is hard, isolation is a big part of the answer. But once you understand the levels and their trade-offs, you can make informed decisions instead of just hoping for the best.&lt;/p&gt;




&lt;p&gt;💬 &lt;strong&gt;Have you run into weird concurrency bugs that disappeared when you cranked up the isolation level?&lt;/strong&gt; I'd love to hear your war stories in the comments!&lt;/p&gt;

</description>
      <category>sql</category>
      <category>postgres</category>
      <category>database</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Atomicity – The "All or Nothing" Magic Behind Database Transactions</title>
      <dc:creator>Mandar Gokhale</dc:creator>
      <pubDate>Tue, 20 May 2025 09:08:56 +0000</pubDate>
      <link>https://dev.to/mandarg13/atomicity-the-all-or-nothing-magic-behind-database-transactions-3f1d</link>
      <guid>https://dev.to/mandarg13/atomicity-the-all-or-nothing-magic-behind-database-transactions-3f1d</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/mandarg13/rediscovering-acid-the-foundation-of-reliable-databases-3h5p"&gt;Part 1&lt;/a&gt;, we explored the four pillars of ACID: &lt;code&gt;Atomicity&lt;/code&gt;, &lt;code&gt;Consistency&lt;/code&gt;, &lt;code&gt;Isolation&lt;/code&gt;, and &lt;code&gt;Durability&lt;/code&gt;. But let's be honest — concepts like these can feel a bit textbook-ish until you hit a real problem and think, &lt;em&gt;"Wait, how does this work under the hood?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's exactly what happened to me.&lt;/p&gt;

&lt;p&gt;I found myself wondering:&lt;br&gt;
&lt;strong&gt;How does the database make sure I don't end up with half-finished data?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question led me to discover one of the most fascinating pieces of database architecture:&lt;br&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt;, and its behind-the-scenes hero — the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  💥 The Banking Disaster That Never Happened
&lt;/h2&gt;

&lt;p&gt;Let's re-look at a simple example: you're transferring ₹100 from Alice to Bob.&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;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks clean, right?&lt;/p&gt;

&lt;p&gt;But what if the server crashes &lt;strong&gt;right after debiting Alice&lt;/strong&gt;, before Bob gets anything?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;😱 Alice loses money. Bob gets nothing. Nobody wins.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's where &lt;strong&gt;atomicity&lt;/strong&gt; steps in — the database's promise that &lt;strong&gt;either everything happens or nothing does&lt;/strong&gt;. No half-cooked data, no side effects.&lt;/p&gt;

&lt;p&gt;But how?&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 Peeking Behind the Curtain: Write-Ahead Logging
&lt;/h2&gt;

&lt;p&gt;One might think that databases simply update data files directly—just write to disk and it's done.&lt;/p&gt;

&lt;p&gt;Turns out, that would be a disaster during a crash. It's like scribbling on a paper while someone's shaking the table — good luck keeping it neat.&lt;/p&gt;

&lt;p&gt;Instead, databases use a strategy that's equal parts paranoid and brilliant:&lt;br&gt;
&lt;strong&gt;Write down your plans first, then act.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt;. It's like the database's diary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Heres exactly what I'm going to do. If I get interrupted, I'll just retrace my steps.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ⚒️ How It Works?
&lt;/h2&gt;

&lt;p&gt;Here's what really happens when you run a transaction:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You start the transaction.&lt;/li&gt;
&lt;li&gt;The database logs every change — &lt;em&gt;not to the table&lt;/em&gt;, but to the WAL.&lt;/li&gt;
&lt;li&gt;When all the changes are logged, the WAL is &lt;strong&gt;flushed to disk&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Only then does the database respond with &lt;strong&gt;COMMIT successful&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The actual table data? That might get updated later.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yes — the real data might still be unchanged after your transaction commits. Mind-bending, right? This completely flipped my understanding. I always thought COMMIT meant "okay, it's definitely written to the database now." But really, it means "I've made an unbreakable promise to write it, and I have the receipt to prove it."&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 When Does the Actual Data Get Updated?
&lt;/h2&gt;

&lt;p&gt;This puzzled me at first. I assumed "commit" meant the database had written the final result.&lt;/p&gt;

&lt;p&gt;But really, the WAL is the source of truth. As long as those logs are safe, the database can recreate the transaction later.&lt;/p&gt;

&lt;p&gt;If the server crashes before it updates the real data? No problem. On restart, it reads the WAL and says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hmm, looks like I promised to credit Bob ₹100. Let me go finish that now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's like waking up and checking your to-do list: "Oh right, I never did step two."&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Flushing the WAL – What Does That &lt;em&gt;Really&lt;/em&gt; Mean?
&lt;/h2&gt;

&lt;p&gt;Here's where I hit another wall.&lt;/p&gt;

&lt;p&gt;Everyone says &lt;em&gt;"WAL is flushed to disk"&lt;/em&gt; but what does that &lt;strong&gt;actually&lt;/strong&gt; mean?&lt;/p&gt;

&lt;p&gt;Turns out, it's a three-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The WAL is written to an in-memory buffer.&lt;/li&gt;
&lt;li&gt;The OS queues that buffer to be written to the disk.&lt;/li&gt;
&lt;li&gt;The database calls &lt;code&gt;fsync()&lt;/code&gt; (or equivalent) to say:&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;"No, don't just promise to write it. &lt;strong&gt;Physically&lt;/strong&gt; write it now."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That last step is critical. Without it, your data could still be floating around in memory buffers, and a power cut would wipe it out.&lt;/p&gt;




&lt;h2&gt;
  
  
  🗂️ What Happens After the WAL is Applied?
&lt;/h2&gt;

&lt;p&gt;Okay, so the transaction is written to the WAL file… and later, it's applied to the actual database. But then what?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the WAL file get deleted?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Is the entry removed after the transaction is committed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not immediately.&lt;/p&gt;

&lt;p&gt;In most databases—like PostgreSQL—the WAL (Write-Ahead Log) files are retained even after the changes they describe have been applied to the data files.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because they serve more purposes than just crash recovery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔄 They support replication to standby servers&lt;/li&gt;
&lt;li&gt;📂 They're used for point-in-time recovery (PITR)&lt;/li&gt;
&lt;li&gt;📦 They can help with logical decoding and incremental backups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The database maintains &lt;strong&gt;checkpoints&lt;/strong&gt; to track which changes have been fully flushed to disk. Once it's sure that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All data changes described in the WAL are safely written to disk, and&lt;/li&gt;
&lt;li&gt;The WAL is no longer needed for replication or recovery...&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...then, and only then, the old WAL segments are marked for &lt;strong&gt;removal&lt;/strong&gt; or &lt;strong&gt;archiving&lt;/strong&gt;, depending on your settings.&lt;/p&gt;

&lt;p&gt;So yes, even after a transaction is committed, the WAL entry sticks around for a while, unless you're in a minimalist config.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 Okay, Hold On — If WAL is kept around, won't it apply the same transaction twice if the DB crashes again and again?
&lt;/h2&gt;

&lt;p&gt;This was my next big question.&lt;/p&gt;

&lt;p&gt;If WAL is replayed after a crash, how does the database avoid applying the &lt;strong&gt;same&lt;/strong&gt; changes more than once?&lt;/p&gt;

&lt;p&gt;The answer: &lt;strong&gt;LSNs — Log Sequence Numbers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each WAL record has an LSN. Every data page also stores the LSN of the last WAL entry it applied.&lt;/p&gt;

&lt;p&gt;During recovery:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the WAL's LSN &amp;gt; page's LSN → apply&lt;/li&gt;
&lt;li&gt;If not → skip it, it's already done&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's like the database saying, &lt;em&gt;"Oh, I already covered this. Moving on."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🔁 The Crash Recovery Sequence
&lt;/h2&gt;

&lt;p&gt;Let's put it all together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You run transaction #101. WAL gets written.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COMMIT&lt;/code&gt; is issued. WAL is flushed to disk.&lt;/li&gt;
&lt;li&gt;💥 Crash! Data pages never got updated.&lt;/li&gt;
&lt;li&gt;Database restarts. Sees WAL for TX 101.&lt;/li&gt;
&lt;li&gt;Applies the changes — based on LSNs.&lt;/li&gt;
&lt;li&gt;Done. The system is back where it was, no data lost.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's &lt;strong&gt;atomicity in action&lt;/strong&gt;. Clean, recoverable, foolproof.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❌ What WAL &lt;em&gt;Doesn't&lt;/em&gt; Do
&lt;/h2&gt;

&lt;p&gt;Here's something I misunderstood for a while:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;WAL doesn't enforce constraints or business logic.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you try to transfer ₹10,000 from an account that only has ₹5, the database rejects the transaction — &lt;em&gt;before&lt;/em&gt; it ever touches the WAL.&lt;/p&gt;

&lt;p&gt;WAL's job starts &lt;strong&gt;after&lt;/strong&gt; the transaction passes all checks.&lt;/p&gt;

&lt;p&gt;So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt; is: "Apply all-or-nothing"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; is: "Only valid transactions are allowed"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mixing those two up is easy — but important to separate.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 PostgreSQL vs MySQL: WAL in the Wild
&lt;/h2&gt;

&lt;p&gt;Different databases use different flavors of WAL:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ PostgreSQL
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Redo log only — applies committed changes during recovery&lt;/li&gt;
&lt;li&gt;Background process updates actual data files&lt;/li&gt;
&lt;li&gt;Controlled with &lt;code&gt;synchronous_commit&lt;/code&gt; setting&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ MySQL (InnoDB)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses both redo and undo logs&lt;/li&gt;
&lt;li&gt;Redo = for committed transactions (like PostgreSQL)&lt;/li&gt;
&lt;li&gt;Undo = for rolling back partial changes&lt;/li&gt;
&lt;li&gt;Controlled with &lt;code&gt;innodb_flush_log_at_trx_commit&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 &lt;strong&gt;Why This Actually Matters (No, Really)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you think &lt;code&gt;COMMIT&lt;/code&gt; is just a magic spell that makes your data safe — think again. Understanding WAL flips the script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💣 &lt;strong&gt;Stop with the micro-transactions&lt;/strong&gt; — every &lt;code&gt;COMMIT&lt;/code&gt; slams a WAL flush. Your database isn’t a vending machine.&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;Bundle your writes&lt;/strong&gt; — batch related changes into one clean, atomic move. It’s not just tidy — it’s smart.&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Delayed durability?&lt;/strong&gt; That’s code for “please lose my data if something crashes.” Use with extreme caution.&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;Know what &lt;code&gt;COMMIT&lt;/code&gt; &lt;em&gt;actually&lt;/em&gt; does&lt;/strong&gt; — it's not fairy dust. It’s a disk write, a sync, and a promise. Respect it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat your transactions like they matter — because they do.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What is WAL?&lt;/td&gt;
&lt;td&gt;A durable log of all pending transaction ops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;When is a transaction "committed"?&lt;/td&gt;
&lt;td&gt;After WAL is flushed to disk (&lt;code&gt;fsync&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What if we crash after commit?&lt;/td&gt;
&lt;td&gt;WAL is replayed — data is recovered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can WAL be applied twice?&lt;/td&gt;
&lt;td&gt;No — LSNs prevent duplicate application&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Does WAL enforce data validity?&lt;/td&gt;
&lt;td&gt;No — it only logs valid transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🕒 Next Up: Isolation
&lt;/h2&gt;

&lt;p&gt;Now that we've uncovered the "A" in ACID, it's time to dive into the most slippery one — &lt;strong&gt;Isolation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Part 3, we'll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What really happens when two users update the same data at the same time&lt;/li&gt;
&lt;li&gt;The difference between repeatable read and serializable&lt;/li&gt;
&lt;li&gt;And what a "phantom read" actually looks like&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I promise — it's weirder and more fun than it sounds.&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>database</category>
      <category>sql</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Rediscovering ACID – The Foundation of Reliable Databases</title>
      <dc:creator>Mandar Gokhale</dc:creator>
      <pubDate>Sun, 18 May 2025 10:42:25 +0000</pubDate>
      <link>https://dev.to/mandarg13/rediscovering-acid-the-foundation-of-reliable-databases-3h5p</link>
      <guid>https://dev.to/mandarg13/rediscovering-acid-the-foundation-of-reliable-databases-3h5p</guid>
      <description>&lt;p&gt;As engineers, we use transactions all the time — &lt;code&gt;BEGIN&lt;/code&gt;, &lt;code&gt;COMMIT&lt;/code&gt;, and maybe a rollback if things go south. But recently, I realized I hadn’t truly internalized what makes those transactions reliable.&lt;/p&gt;

&lt;p&gt;That curiosity led me to revisit the ACID properties — a foundational concept we all learn early on but rarely pause to deeply understand. What started as a quick refresher turned into a deep dive into atomicity, consistency, isolation, and durability, and how real databases like PostgreSQL and MySQL implement them.&lt;/p&gt;

&lt;p&gt;Along the way, I discovered that one core mechanism — the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt; — is key to both Atomicity and Durability, playing a foundational role in keeping transactions safe and recoverable.&lt;/p&gt;

&lt;p&gt;In this first part of a multi-part series, I’ll walk through what each property means, why it matters, and where it shows up in real-world systems. We'll ground the theory with SQL examples you can run yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔹 What is ACID?
&lt;/h2&gt;

&lt;p&gt;ACID stands for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt; – All or nothing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency&lt;/strong&gt; – The database moves from one valid state to another&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation&lt;/strong&gt; – Transactions don’t interfere with each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durability&lt;/strong&gt; – Once committed, data is forever&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s look at each one with practical examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧱 Atomicity – All or Nothing
&lt;/h2&gt;

&lt;p&gt;A transaction must either &lt;strong&gt;complete entirely or not at all&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine transferring ₹100 from Alice to Bob:&lt;br&gt;&lt;br&gt;
Debit Alice. Credit Bob. If only one of those happens, the system is in a bad state.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- crash happens here&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;COMMIT&lt;/code&gt; never happened, PostgreSQL will &lt;strong&gt;rollback&lt;/strong&gt; the entire transaction automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  📐 Consistency – Enforcing Rules
&lt;/h2&gt;

&lt;p&gt;A database should always transition from one &lt;strong&gt;valid&lt;/strong&gt; state to another. That includes enforcing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data types&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Foreign keys&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application invariants&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ✅ Example 1: Check constraint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;check_balance&lt;/span&gt; &lt;span class="k"&gt;CHECK&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;-- ❌ rejected if Alice only has ₹1000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Example 2: Foreign key constraint
&lt;/h3&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;customers&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&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;name&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&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="nb"&gt;SERIAL&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="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;-- ❌ This fails&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&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;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PostgreSQL blocks the insertion because customer 999 doesn’t exist.&lt;/p&gt;

&lt;p&gt;ℹ️ Note:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The database does not define consistency on its own — it simply enforces the rules you define.&lt;br&gt;
If your schema or application logic doesn't include constraints, the database won't protect them automatically.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🔒 Isolation – Transactions Don’t Bump Into Each Other
&lt;/h2&gt;

&lt;p&gt;This is the most subtle — and arguably the most important — part of ACID. Isolation means each transaction should act like it’s the &lt;strong&gt;only one running&lt;/strong&gt;, even in a highly concurrent system.&lt;/p&gt;

&lt;p&gt;Databases offer multiple &lt;strong&gt;isolation levels&lt;/strong&gt; to balance correctness and performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read Uncommitted&lt;/li&gt;
&lt;li&gt;Read Committed&lt;/li&gt;
&lt;li&gt;Repeatable Read&lt;/li&gt;
&lt;li&gt;Serializable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In upcoming part, we’ll go deep into isolation levels, MVCC, and real-world concurrency bugs.&lt;/p&gt;




&lt;h2&gt;
  
  
  💾 Durability – Survives Crashes
&lt;/h2&gt;

&lt;p&gt;Once you &lt;code&gt;COMMIT&lt;/code&gt;, it’s &lt;strong&gt;permanent&lt;/strong&gt; — even if the database crashes 1ms later.&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;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt; &lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How is that possible? That’s what we’ll explore in detail in Part 2 — where we discuss &lt;strong&gt;WAL (Write-Ahead Logging)&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Coming Up Next
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/mandarg13/atomicity-the-all-or-nothing-magic-behind-database-transactions-3f1d"&gt;next post&lt;/a&gt;, we’ll dive into how databases like PostgreSQL use the &lt;strong&gt;Write-Ahead Log (WAL)&lt;/strong&gt; — the invisible hero behind safe commits and crash recovery — to guarantee &lt;strong&gt;atomicity&lt;/strong&gt;, ensuring that a transaction either completes fully or not at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ TL;DR Cheatsheet
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Property&lt;/th&gt;
&lt;th&gt;What it Means&lt;/th&gt;
&lt;th&gt;Example Scenario&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Atomicity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All-or-nothing transactions&lt;/td&gt;
&lt;td&gt;Debit and credit in money transfer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consistency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rules must be upheld&lt;/td&gt;
&lt;td&gt;Check constraints, foreign key enforcement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Isolation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Concurrent transactions don't clash&lt;/td&gt;
&lt;td&gt;Read same row, don't see other's changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Durability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Committed = permanent&lt;/td&gt;
&lt;td&gt;Crash-safe after &lt;code&gt;COMMIT&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Thanks for reading! If you enjoyed this, stay tuned for the next post in the series — and feel free to share your own “aha” moments around ACID in the comments!&lt;/p&gt;

</description>
      <category>sql</category>
      <category>database</category>
      <category>postgres</category>
      <category>mysql</category>
    </item>
  </channel>
</rss>
