Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
160611 stories
·
33 followers

Advocating Uptime: Schema Changes in 6 Phases

1 Share

Schema change is inevitable. We do not get everything right the first time, and even when we do, the world around the database keeps changing. Requirements mature, products evolve, and assumptions that made sense years ago eventually stop matching reality.

Businesses change too. We acquire companies, merge with other customers and systems, enter new markets, and adapt to new opportunities. Sometimes a schema has to change because the original design was wrong. More often, it changes because the business is no longer the same business that existed when the schema was designed.

That is normal. The challenge is not avoiding schema change. The challenge is making those changes without interrupting the applications and users that depend on the database.

Spoiler alert

If there is anything that should be said about maintaining uptime through schema change, it should be: don’t get in a hurry. A sensible approach is a phased approach. It’s tempting to jump ahead, but read through this article and you’ll hopefully conclude that an intentional approach preserves integrity and eliminates downtime.

A simple example

Consider something simple: a Name column in a User table needs to become FirstName and LastName. The final schema is straightforward. Getting there safely in production is not. If uptime matters, this becomes a multi-phase migration where old and new application versions can coexist while the database evolves underneath them.

table to table image

Phase 1: Add columns FirstName and LastName

The safest first step is also the simplest: add the new columns without changing anything the application already depends on.

ALTER TABLE dbo.[User]
ADD
    FirstName nvarchar(100) NULL,
    LastName  nvarchar(100) NULL;

At this point, Name remains exactly where it was. Existing application instances continue reading and writing it, while the new columns simply wait for the next phase.

This is the “expand” part of the expand-and-contract pattern. We are making the schema larger before making it smaller. Nothing has been renamed, removed, or made incompatible.

Making the new columns nullable is intentional.

Existing rows do not have values for them yet, and requiring values immediately would turn a harmless additive change into a migration problem. We will populate them later, validate them, and only then decide whether stronger constraints make sense.

The important idea is sequencing

Deploy the database change first. Once every production database understands both the old and new schema, we can safely begin deploying application code that understands both as well.

Phase 2: Dual-Write Old and New Columns

Now that the database understands both shapes, the application can begin writing both.

user.Name = $"{user.FirstName} {user.LastName}";
user.FirstName = firstName;
user.LastName = lastName;

The exact implementation will vary, but the principle is the same: every insert or update that affects a user’s name must keep Name, FirstName, and LastName synchronized.

This phase is what allows old and new application versions to coexist. Older instances can continue reading Name. Newer instances can begin working with FirstName and LastName. Because both representations are written together, neither version sees stale data.

There is a subtle sequencing requirement here

Start dual-writing before you start reading from the new columns. Existing rows have not been backfilled yet, so FirstName and LastName may still be NULL. Dual-write only guarantees that data changed from this point forward is correct in both representations.

You may be tempted to solve this with a trigger.

That can work, but I generally prefer putting the synchronization in the application when possible. The application understands the semantics of the change, keeps the migration logic visible, and makes it easier to remove later. A trigger can be useful when multiple applications write directly to the table and you cannot update all of them at once.

You may be tempted to solve this with a stored procedure.

That can work well, especially if all writes already flow through a stored procedure. In that case, updating one database boundary may be simpler than changing every caller. The procedure can accept FirstName and LastName, continue populating Name, and preserve compatibility while applications migrate.

The downside is similar to any abstraction introduced only for a migration: it becomes another layer that has to be deployed, understood, and eventually removed. I would use it when stored procedures are already part of the application’s write path, but I would not introduce one solely to avoid a straightforward application change.

At the end of this phase, every new write is safe for both the old schema and the new schema. The historical data is the only thing left behind.

Phase 3: Backfill Existing Rows

Now that every new write keeps both representations synchronized, we can turn our attention to the rows that already existed before the application change. The goal is simple: populate FirstName and LastName from Name without interfering with normal production traffic.

UPDATE dbo.[User]
SET
    FirstName = LEFT(Name, CHARINDEX(' ', Name + ' ') - 1),
    LastName = LTRIM(SUBSTRING(
        Name,
        CHARINDEX(' ', Name + ' ') + 1,
        LEN(Name)
    ))
WHERE FirstName IS NULL
   OR LastName IS NULL;

Real names are messy.

The parsing logic here is intentionally simple for the example. Prefixes, suffixes, compound surnames, single-word names, and cultural naming conventions can make splitting a name surprisingly difficult. In a real migration, this transformation deserves its own validation and may not be practical in T-SQL.

The more important production concern is how much data we update at once. A single large UPDATE can hold locks, grow the transaction log, and create unnecessary pressure on the system. For a large table, backfill in batches.

WHILE 1 = 1
BEGIN
    UPDATE TOP (1000) dbo.[User]
    SET
        FirstName = LEFT(Name, CHARINDEX(' ', Name + ' ') - 1),
        LastName = LTRIM(SUBSTRING(
            Name,
            CHARINDEX(' ', Name + ' ') + 1,
            LEN(Name)
        ))
    WHERE FirstName IS NULL
       OR LastName IS NULL;

    IF @@ROWCOUNT = 0
        BREAK;
END

This is one of the benefits of dual-write happening first. While the backfill works through historical rows, every new insert or update is already maintaining the new columns. The migration is moving forward without requiring the application to stop.

At the end of this phase, old rows and new rows have the same shape. The database now contains both representations for every user, which means we can safely begin changing how the application reads the data.

Phase 4: Move Reads to the New Columns

At this point, every row has values in FirstName and LastName, and every new write keeps those columns synchronized with Name. Now the application can begin reading from the new schema.

SELECT
    Id,
    FirstName,
    LastName,
    Email
FROM dbo.[User];

This should still be treated as a deployment phase, not a cleanup phase. The Name column remains in place because older application instances may still be running, and other consumers may still depend on it.

The safest approach is to deploy the read change gradually and verify that nothing breaks. If your application supports staged rollout, canary deployment, or feature flags, this is a good place to use them. The database now supports both shapes, so the application can move forward without forcing every consumer to change at the same moment.

Once all supported application versions are reading FirstName and LastName, the primary application no longer depends on Name.

You might be tempted to remove read permissions from the old column.

That can seem like a useful way to flush out anything still depending on Name, but in production it turns discovery into an outage. Reports, jobs, scripts, or older application instances may still be reading the column.

A safer approach is to observe usage, update known consumers, and leave the old column readable until you are confident nothing depends on it. Permissions are better used to enforce the final state than to test whether you missed something.

How to observe usage?

Query Store is a good place to start because it can reveal recent queries still referencing the old column. Application logs, database logs, dependency metadata, and temporary Extended Events can also help identify active consumers. None is complete by itself, so combine approaches and use the tooling appropriate for your environment.

Don’t forget about reports

Your application may not be the only thing reading this table. Reports, ETL jobs, exports, scripts, scheduled jobs, notebooks, and downstream services may still reference Name.

Before declaring the old column obsolete, search for those dependencies and give their owners time to migrate. This is one reason the phased approach matters: keeping Name available costs very little, while removing it too early can break consumers you did not know existed.

At the end of this phase, reads have moved to the new schema, but writes still maintain both representations. That gives us one more compatibility window before we stop maintaining Name.

Phase 5: Stop Writing Name

By now, the application reads from FirstName and LastName, and we have given other consumers time to move away from Name. The next step is to stop maintaining the old representation. Remove the dual-write logic so inserts and updates write only the new columns.

user.FirstName = firstName;
user.LastName = lastName;

At this point, Name becomes stale by design. That is okay because nothing should depend on it anymore.

This phase is another useful checkpoint.

Do not remove the column yet. Leaving Name in place for a while gives you time to confirm that no application, report, job, or downstream process unexpectedly starts failing once the old value stops changing. The important distinction is that Name is now deprecated, not deleted. We have stopped investing in its correctness before taking the irreversible step of removing it.

At the end of this phase, the new schema is the only schema being actively maintained. The old column remains only as a compatibility buffer while we validate that the transition is complete.

Phase 6: Validate and Remove the Old Schema

Congratulations! At this point, the migration is functionally complete. The application reads and writes only FirstName and LastName, and Name has been left in place long enough to prove that nothing still depends on it.

Before removing the old column

Before removing the old column, validate the new state. Confirm that expected rows have values, investigate any unexpected NULL values, verify that reports and downstream consumers have moved, and add any final constraints or indexes that belong on the new columns.

Once that validation is complete, the old column can finally be removed.

ALTER TABLE dbo.[User]
    DROP COLUMN Name;

This is the “contract” part of expand-and-contract. We expanded the schema first, allowed old and new versions to coexist, moved writes, backfilled data, moved reads, stopped maintaining the old shape, and only now remove it. The important point is that dropping the column should be boring. By the time you execute this statement, nothing should notice.

The Pattern Is the Point

This example is intentionally simple, but the pattern scales. Expand the schema first. Let old and new representations coexist. Move writes, move data, move reads, validate, and only then contract the schema. The individual SQL statements are easy. The discipline is in the sequencing.

The post Advocating Uptime: Schema Changes in 6 Phases appeared first on Azure SQL Dev Corner.

Read the whole story
alvinashcraft
36 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Numerics.NET with Jeffrey Sax

1 Share
So what can numerics do for you? Carl and Richard talk to Jeffrey Sax about his work building Numerics.NET, a collection of general-purpose mathematical and statistical classes built for .NET. Jeffrey explains that numbers in a computer differ from real numbers in the world; for storage and computational efficiency, typical variable types in any programming language have limits on precision and size. How those variables are used can affect the outcome, with potentially disastrous consequences. Numerics.net provides exacting control of precision, as well as complex mathematical functions. It's far from free - but if you need it, you need it!



Download audio: https://dts.podtrac.com/redirect.mp3/api.spreaker.com/download/episode/74875534/dotnetrocks_2019_numerics_dot_net.mp3
Read the whole story
alvinashcraft
49 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

Mistakes That Make Investors Nervous, According to a PhD in Pitching

1 Share

There is no such thing as the perfect pitch. But you can get close by implementing a few research-backed methods to your delivery, deck, and message.

In this episode of Build Mode, host Isabelle Johannesen sits down with Dr. Eike Gerhardt, who has aPhD in pitching and spent nearly a decade studying the science of startup pitching before starting Autopoiesis Sciences. And he’s joined by Demetri Maxim, co-founder and CEO of Nephrogen, who came in second at TechCrunch Startup Battlefield 2025.

Together, they break down Demetri’s actual Startup Battlefield pitch to unpack what worked, what could be improved, and what research tells us about how investors respond to founders. Eike explains why credibility signals matter, how technical founders can simplify without oversimplifying, and why Q&A should be treated as a second pitch. Demetri shares how he learned to explain complex biotech to generalist investors, how redesigning his deck changed his confidence onstage, and what he would do differently today.

They also explore how body language and authenticity affect a pitch, how investor questions can reveal bias, and how founders can use AI to prepare for difficult Q&A.

They get into:

  • What Demetri got right and in his Startup Battlefield pitch

  • How to explain complicated technology without oversimplifying it

  • The credibility signals investors look for in a pitch

  • Why some technical language can actually make founders more credible

  • How to decide what belongs in your pitch versus the Q&A

  • Why technical details can sometimes make your startup sound riskier

  • How body language and authenticity influence investors

  • Why Q&A should be treated as a second pitch

  • What research reveals about bias in investor questions

  • How to use AI to rehearse difficult investor Q&A

  • Why there is no single “perfect” startup pitch

  • The biggest pitching mistakes technical founders make

Here are the studies mentioned in the episode:

  • Kanze, D., Huang, L., Conley, M. A., & Higgins, E. T. (2018). “We Ask Men to Win and Women Not to Lose: Closing the Gender Gap in Startup Funding.” Academy of Management Journal https://doi.org/10.5465/amj.2016.1215

  • Figge, P., Graf-Vlachy, L., König, A., Demann, F., & Diessner, M. (2025). “Shades of Grey or Black and White? How Entrepreneurs’ Use of Cognitively Complex Language Affects Investor Funding.” Entrepreneurship Theory and Practice https://doi.org/10.1177/10422587251347042

  • Clarke, J. S., Cornelissen, J. P., & Healey, M. P. (2019). “Actions Speak Louder than Words: How Figurative Language and Gesturing in Entrepreneurial Pitches Influences Investment Judgments.” Academy of Management Journal https://doi.org/10.5465/amj.2016.1008

  • Jiang, L., Yin, D., & Liu, D. (2019). “Can Joy Buy You Money? The Impact of the Strength, Duration, and Phases of an Entrepreneur’s Peak Displayed Joy on Funding Performance.” Academy of Management Journal. https://doi.org/10.5465/amj.2017.1423

  • Chen, X.-P., Yao, X., & Kotha, S. (2009). “Entrepreneur Passion and Preparedness in Business Plan Presentations: A Persuasion Analysis of Venture Capitalists’ Funding Decisions.” Academy of Management Journal https://doi.org/10.5465/amj.2009.36462018

  • Zhu, L. Y., Young, M. J., & Bauman, C. W. (2024). “Linking Anxiety to Passion: Emotion Regulation and Entrepreneurs’ Pitch Performance.” Journal of Business Venturing https://doi.org/10.1016/j.jbusvent.2024.106421Allison, T. H., Davis, B. C., Webb, J. W., & Short, J. C. (2017). “Persuasion in Crowdfunding: An Elaboration Likelihood Model of Crowdfunding Performance.” Journal of Business Venturing https://doi.org/10.1016/j.jbusvent.2017.09.002Clark, C. (2008). “The Impact of Entrepreneurs’ Oral ‘Pitch’ Presentation Skills on Business Angels’ Initial Screening Investment Decisions.” Venture Capital https://doi.org/10.1080/13691060802151945

Subscribe to Build Mode on Apple Podcasts, Spotify, or wherever you like to listen. And watch the full videos on YouTube. New episodes of Build Mode drop every Thursday.

Hosted by Isabelle Johannesen. Produced and edited by Maggie Nye. Audience development led by Morgan Little. Special thanks to the Foundry and Cheddar video teams.






Download audio: https://www.podtrac.com/pts/redirect.mp3/traffic.megaphone.fm/TCML1022902347.mp3
Read the whole story
alvinashcraft
56 seconds ago
reply
Pennsylvania, USA
Share this story
Delete

5 things you didn't know about Azure SQL Database Hyperscale | Data Exposed

1 Share
From: Microsoft Developer
Duration: 7:39
Views: 397

Azure SQL Database Hyperscale has been around for some time, but there's many things that are different about it that you may not know. Listen to Bob Ward and Anna Hoffman discuss, and comment with what you think people should know!

✅ Chapter:
0:10 5 things you didn't know about Azure SQL Database Hyperscale
0:50 The Hyperscale name: not just for big databases
1:45 What's special about the Hyperscale architecture, separating storage from compute
3:10 Named replicas, high availability replicas, 'read scale on the fly'
5:15 How backups are different, snapshot backups
6:15 Priced at open-source
7:00 What else

✅ Resources:
Watch the series: https://aka.ms/azuresqlfoundationseries

Get the repos: https://aka.ms/azuresqlfoundations

Hyperscale FAQ: https://learn.microsoft.com/azure/azure-sql/database/service-tier-hyperscale-frequently-asked-questions-faq?view=azuresql

📌 Let's connect:
Twitter - Bob Ward, https://twitter.com/bobwardms
Twitter - Anna Hoffman, https://twitter.com/AnalyticAnna
Twitter - AzureSQL, https://aka.ms/azuresqltw

🔴 Watch even more Data Exposed episodes: https://aka.ms/dataexposedyt

🔔 Subscribe to our channels for even more SQL tips:
Microsoft Azure SQL: https://aka.ms/msazuresqlyt
Microsoft SQL Server: https://aka.ms/mssqlserveryt
Microsoft Developer: https://aka.ms/microsoftdeveloperyt

#AzureSQL #SQL #LearnSQL

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Agent Substrate, with Tim Hockin and Brandon Royal

1 Share

Tim Hockin is a long term software engineer with Google Cloud and I would argue one of the fathers of Kubernetes. Brandon Royal is a product manager on GKE and has been behind the launch of multiple OSS projects like the Ray Operator for k8s, Agent Sandbox and our topic for today - Agent Substrate.

 

Do you have something cool to share? Some questions? Let us know:

- web: kubernetespodcast.com

- mail: kubernetespodcast@google.com

- twitter: @kubernetespod

- bluesky: @kubernetespodcast.com

 

News of the week

Links from the interview

Links from the post-interview chat





Download audio: https://traffic.libsyn.com/secure/e780d51f-f115-44a6-8252-aed9216bb521/KPOD272.mp3?dest-id=3486674
Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete

Uno Platform Studio 3.1 Overview

1 Share
From: UnoPlatform
Duration: 8:58
Views: 18

Four additions to the Uno Platform Studio loop: previews for every UI state, drag-in snippets, select-and-prompt for precise agent context, and a neutral default theme built to be made your own.

https://platform.uno/blog/uno-platform-studio-3-1/

Read the whole story
alvinashcraft
1 minute ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories