<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>SQL on Vedant Andhale</title>
    <link>https://www.vedant.me/tags/sql/</link>
    <description>Recent content in SQL on Vedant Andhale</description>
    <image>
      <url>https://www.vedant.me/</url>
      <link>https://www.vedant.me/</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 10 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.vedant.me/tags/sql/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>A database migration has to coexist with old code</title>
      <link>https://www.vedant.me/notebook/migrations-that-do-not-wake-you-up/</link>
      <pubDate>Thu, 10 Sep 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.vedant.me/notebook/migrations-that-do-not-wake-you-up/</guid>
      <description>An expand-and-contract example for schema changes that must work while application versions overlap.</description>
      <content:encoded><![CDATA[<p>Changing a database column is easy to describe when one application process owns the database and can stop for the change. A deployed service often has a messier interval: old and new application instances may run at the same time.</p>
<p>That interval is where a simple column rename can break otherwise correct code. The new version asks for the new name while the old version still asks for the old one.</p>
<h2 id="add-before-removing">Add before removing</h2>
<p>Suppose <code>customers.name</code> needs to become <code>customers.display_name</code>. An illustrative transition is:</p>
<ol>
<li>Add the new nullable column while keeping the old column usable.</li>
<li>Deploy code that writes both values in the same transaction and can read through the transition.</li>
<li>Backfill existing rows in bounded batches, with a retry-safe condition.</li>
<li>Check that all writers have migrated and the backfill is complete.</li>
<li>Switch reads to the new field; remove the old field in a later change.</li>
</ol>
<p>The details depend on the database and workload. A batch backfill can race with live updates, and a forgotten background job may still write only the old column. The compatibility plan needs to include those writers, not just the web application.</p>
<h2 id="separate-reversible-steps">Separate reversible steps</h2>
<p>Before removing a column, rolling the application back may still be straightforward. After deletion, the previous code can no longer rely on the data it expects. Treat that deletion as a separate decision with its own verification and recovery plan.</p>
<p>The SQL statement&rsquo;s apparent simplicity also says little about its operational cost. Check the database version&rsquo;s behaviour for locks, table scans and constraint validation. Rehearse on a representative dataset when those costs could interrupt traffic.</p>
<p>A useful migration note explains what can run during each stage, how completion is checked, and what rollback means at that point. That note is often more valuable than a clever one-line migration.</p>
<p>Reference: <a href="https://www.postgresql.org/docs/current/ddl-alter.html">PostgreSQL documentation on modifying tables</a>.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
