{"id":1439,"date":"2026-10-20T18:00:00","date_gmt":"2026-10-20T17:00:00","guid":{"rendered":"https:\/\/wade.one\/blog\/?p=1439"},"modified":"2026-10-20T18:00:00","modified_gmt":"2026-10-20T17:00:00","slug":"database-migrations-need-to-survive-two-app-versions-at-once","status":"publish","type":"post","link":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/","title":{"rendered":"Database Migrations Need to Survive Two App Versions at Once"},"content":{"rendered":"<p>A database migration can work perfectly on your development machine and still make a production deployment awkward. During a rolling release, some application instances may be running the old code while others use the new code. If the schema change immediately removes something the old version expects, the deployment order becomes a trap.<\/p>\n<p>The <a href=\"https:\/\/www.prisma.io\/docs\/guides\/database\/data-migration\">expand-and-contract approach<\/a> separates adding the new structure from removing the old one. Introduce a compatible shape, move the application and data across, then remove the obsolete structure when it is genuinely unused. It creates more than one step, but each step has a clearer relationship with the code currently running.<\/p>\n<p>I would pay particular attention to data written during the transition. A backfill of yesterday&#8217;s rows does not automatically handle today&#8217;s new writes, and a rollback may be useless if the older application cannot understand the updated records. Decide how those cases work before treating a successful migration command as proof that the release is safe.<\/p>\n<p>Small deployments are easier to manage when the database lets the application move gradually. The aim is a change you can explain and recover from, with checks at each boundary. Saving one migration file is not worth making every instance switch versions at exactly the same moment.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A database migration can work perfectly on your development machine and still make a production deployment awkward.<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_hide_featured_image":false,"_jetpack_featured_image_duplicate_dismissed":0,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[13],"tags":[269,61,270],"class_list":["post-1439","post","type-post","status-publish","format-standard","hentry","category-programming","tag-database-migrations","tag-deployments","tag-prisma"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Database Migrations Need to Survive Two App Versions at Once - wade.one<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Database Migrations Need to Survive Two App Versions at Once - wade.one\" \/>\n<meta property=\"og:description\" content=\"A database migration can work perfectly on your development machine and still make a production deployment awkward.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/\" \/>\n<meta property=\"og:site_name\" content=\"wade.one\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-20T17:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1518\" \/>\n\t<meta property=\"og:image:height\" content=\"1506\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:site\" content=\"@wadewomersley\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Database Migrations Need to Survive Two App Versions at Once\",\"datePublished\":\"2026-10-20T17:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/\"},\"wordCount\":219,\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"keywords\":[\"database-migrations\",\"deployments\",\"prisma\"],\"articleSection\":[\"Programming\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/\",\"name\":\"Database Migrations Need to Survive Two App Versions at Once - wade.one\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-20T17:00:00+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/2026\\\/10\\\/20\\\/database-migrations-need-to-survive-two-app-versions-at-once\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/wade.one\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Database Migrations Need to Survive Two App Versions at Once\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/\",\"name\":\"wade.one\",\"description\":\"wade womersley - york based software engineer\",\"publisher\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/wade.one\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/#\\\/schema\\\/person\\\/8b4739f8f8bb2cff5d792d4b8779fcc3\",\"name\":\"Wade Womersley\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"url\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"contentUrl\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\",\"width\":202,\"height\":200,\"caption\":\"Wade Womersley\"},\"logo\":{\"@id\":\"https:\\\/\\\/wade.one\\\/blog\\\/wp-content\\\/uploads\\\/2015\\\/02\\\/200px.png\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Database Migrations Need to Survive Two App Versions at Once - wade.one","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/","og_locale":"en_GB","og_type":"article","og_title":"Database Migrations Need to Survive Two App Versions at Once - wade.one","og_description":"A database migration can work perfectly on your development machine and still make a production deployment awkward.","og_url":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/","og_site_name":"wade.one","article_published_time":"2026-10-20T17:00:00+00:00","og_image":[{"width":1518,"height":1506,"url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/Wade-Logo-cropped.png","type":"image\/png"}],"twitter_card":"summary_large_image","twitter_creator":"@wadewomersley","twitter_site":"@wadewomersley","twitter_misc":{"Estimated reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/#article","isPartOf":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/"},"author":{"name":"","@id":""},"headline":"Database Migrations Need to Survive Two App Versions at Once","datePublished":"2026-10-20T17:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/"},"wordCount":219,"publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"keywords":["database-migrations","deployments","prisma"],"articleSection":["Programming"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/","url":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/","name":"Database Migrations Need to Survive Two App Versions at Once - wade.one","isPartOf":{"@id":"https:\/\/wade.one\/blog\/#website"},"datePublished":"2026-10-20T17:00:00+00:00","breadcrumb":{"@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/wade.one\/blog\/2026\/10\/20\/database-migrations-need-to-survive-two-app-versions-at-once\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/wade.one\/blog\/"},{"@type":"ListItem","position":2,"name":"Database Migrations Need to Survive Two App Versions at Once"}]},{"@type":"WebSite","@id":"https:\/\/wade.one\/blog\/#website","url":"https:\/\/wade.one\/blog\/","name":"wade.one","description":"wade womersley - york based software engineer","publisher":{"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/wade.one\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":["Person","Organization"],"@id":"https:\/\/wade.one\/blog\/#\/schema\/person\/8b4739f8f8bb2cff5d792d4b8779fcc3","name":"Wade Womersley","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","url":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","contentUrl":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png","width":202,"height":200,"caption":"Wade Womersley"},"logo":{"@id":"https:\/\/wade.one\/blog\/wp-content\/uploads\/2015\/02\/200px.png"}}]}},"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1394,"url":"https:\/\/wade.one\/blog\/2026\/08\/15\/mcp-going-stateless-is-the-boring-fix-it-needed\/","url_meta":{"origin":1439,"position":0},"title":"MCP Going Stateless Is the Boring Fix It Needed","author":"","date":"August 15, 2026","format":false,"excerpt":"MCP's stateless core removes deployment plumbing that should never have been the interesting part of an agent tool.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1432,"url":"https:\/\/wade.one\/blog\/2026\/10\/13\/php-8-2-needs-an-upgrade-plan-before-the-end-of-2026\/","url_meta":{"origin":1439,"position":1},"title":"PHP 8.2 Needs an Upgrade Plan Before the End of 2026","author":"","date":"October 13, 2026","format":false,"excerpt":"PHP 8.2 is approaching the end of its security support window on 31 December 2026.","rel":"","context":"In &quot;PHP&quot;","block_context":{"text":"PHP","link":"https:\/\/wade.one\/blog\/category\/php\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1472,"url":"https:\/\/wade.one\/blog\/2026\/10\/29\/a-database-constraint-can-close-the-gap-between-checking-and-writing\/","url_meta":{"origin":1439,"position":2},"title":"A Database Constraint Can Close the Gap Between Checking and Writing","author":"","date":"October 29, 2026","format":false,"excerpt":"Checking whether a record exists before inserting another one does not guarantee uniqueness.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1160,"url":"https:\/\/wade.one\/blog\/2026\/03\/27\/what-makes-a-legacy-system-dangerous\/","url_meta":{"origin":1439,"position":3},"title":"What Makes a Legacy System Dangerous","author":"","date":"March 27, 2026","format":false,"excerpt":"A legacy system is not dangerous just because it is old. It becomes dangerous when nobody can change it safely, nobody can see what it is doing, and the business depends on it anyway.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1170,"url":"https:\/\/wade.one\/blog\/2026\/04\/03\/why-environment-management-gets-messy-faster-than-people-expect\/","url_meta":{"origin":1439,"position":4},"title":"Why Environment Management Gets Messy Faster Than People Expect","author":"","date":"April 3, 2026","format":false,"excerpt":"Environment management usually looks simple at first. Then defaults drift, secrets spread out, local setups stop matching production, and the whole thing becomes a source of avoidable mistakes.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1434,"url":"https:\/\/wade.one\/blog\/2026\/10\/15\/read-the-postgresql-query-plan-before-adding-another-index\/","url_meta":{"origin":1439,"position":5},"title":"Read the PostgreSQL Query Plan Before Adding Another Index","author":"","date":"October 15, 2026","format":false,"excerpt":"When a database query gets slow, adding an index is an appealingly concrete thing to do.","rel":"","context":"In &quot;Programming&quot;","block_context":{"text":"Programming","link":"https:\/\/wade.one\/blog\/category\/programming\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1439","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/comments?post=1439"}],"version-history":[{"count":1,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1439\/revisions"}],"predecessor-version":[{"id":1462,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/posts\/1439\/revisions\/1462"}],"wp:attachment":[{"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/media?parent=1439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/categories?post=1439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wade.one\/blog\/wp-json\/wp\/v2\/tags?post=1439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}