Zero-Downtime Database Migration for Business Applications: Expand-Migrate-Contract, Backfills, and Rollback Plans
In this article
- Summary
- Why database migration is risky
- The basic principle: expand, migrate, contract
- Types of change and their risk level
- Moving large data without disturbing users
- Rollback plan and backups
- Testing before the day
- Big migrations: changing database engine or provider
- When a maintenance window is actually better
- Collaboration between business and technical teams
- A short checklist before running a migration
- Frequently asked questions
- Conclusion
Every business application that stays alive will change. New features need new columns, new reports need new tables, and data growth forces old structures to be reorganized. The problem is that the database is the hardest part of an application to change while it is in use. Program code can be replaced in seconds with a new release, but a table holding millions of rows of orders, invoices, and stock cannot be "switched off for a moment" without consequences. Many businesses end up choosing a midnight maintenance window or, worse, postponing changes until technical debt piles up.
This article explains how to change the structure of a business application's database with minimal risk and, where possible, without stopping the service: gradual change patterns, how to move large data, rollback plans, and testing. It is meant for business owners and product managers who need to understand the technical decisions behind a change, and for technical teams looking for a practical framework.
Summary
- Safe database changes are made gradually with an "expand, migrate, contract" pattern, not in a single swap
- Always prepare a rollback plan and a backup whose restore has been tested before touching production data
- Move large data in small chunks in the background so tables are not locked and users are not slowed down
- Test the migration on a copy of production data, measure the time, and rehearse the procedure before the day
- Communicate the schedule and risks to business users; not every change needs zero downtime, but every change needs a plan

Why database migration is risky
A database structure change differs from a code change for two reasons: data is permanent, and the change often affects the whole application at once.
- **Data cannot be "replaced"**: a code mistake can be fixed with a new release, but corrupted or deleted data can only be recovered from a backup
- **Table locking**: some structure changes lock the table while they run, so the application waits or errors
- **Version compatibility**: during a release, old and new versions of the code may run side by side and both must fit the database structure
- **Scale**: a change that finishes in one second on test data can take an hour on production data
- **Hidden dependencies**: reports, integrations, and old scripts may read the column you are about to change
For this reason, a database migration should be treated as a small project with preparation, testing, and a way back, not a routine task done in passing.
The basic principle: expand, migrate, contract
The most widely used pattern for no-downtime changes is often called "expand and contract". The idea: never change something in a way that immediately breaks the old code version.
Stage 1: expand
Add the new structure without removing the old. For example, to split a full name column into first and last names, add the two new columns first. The old column stays and is still used. Adding an optional column is usually quick and safe.
Stage 2: migrate
Change the application to write to both old and new structures, then copy historical data from old to new gradually. Once all data is copied and consistent, change the application to read from the new structure. Throughout this period both code versions keep working.
Stage 3: contract
When you are sure nothing uses the old structure, stop writing to it, then delete the old column or table in a later release. Do not rush: keep the old structure for a while as a safety net.
This pattern takes more steps than changing everything at once, but each step is small, reversible, and does not interrupt service. It fits with feature flags and gradual rollouts, which allow switching to new behavior at low risk.
Types of change and their risk level
Not all changes are equal. Recognizing the risk level helps decide whether a maintenance window is needed.
Low-risk changes
- Adding a new table that old code does not use yet
- Adding an optional column without a heavy default value
- Adding an index with a method that does not lock the table (where the database engine supports it)
Medium-risk changes
- Changing a column's data type, especially on large tables
- Adding a required column with a default value to a table of millions of rows
- Adding a constraint to existing data, because old data must be validated
High-risk changes
- Renaming a column or table used by many parts of the application
- Dropping a column or table
- Splitting or merging large tables
- Moving the database to another engine or provider
For high-risk changes, always use the gradual pattern. A rename should be done by adding the new name, copying, switching over, and then deleting the old name, not with a direct rename command.
Moving large data without disturbing users
Copying millions of rows in one big transaction can lock the table, exhaust memory, and make database replicas lag. A safer way is to fill the data in small chunks (a backfill).
A safe backfill pattern
- **Small chunks**: process thousands of rows per round, not millions at once
- **Pauses between rounds**: add a short pause so database load stays low for users
- **Resumable**: record the last position so an interrupted process can continue rather than restart
- **Idempotent**: running the same chunk twice does not corrupt data
- **Monitoring**: watch application response times, queues, and replication lag while it runs
- **Timing**: run outside peak hours, such as outside store transaction hours or the month-end close
This approach is similar to background processing in event-driven architecture and message queues: heavy work is split into small units that can be retried.
Handling new data that arrives during migration
While old data is being copied, users keep creating new data. Make sure the application writes to both structures (dual write), or use a change-capture mechanism (triggers or a change log) so no row is missed. When finished, run a consistency check: row counts, total values, and random samples must match between the old and new structures.
Rollback plan and backups
The most important question before a migration is: "If this fails, how do we go back?" A team without a clear answer is not ready to migrate.
A backup that can actually be restored
Having a backup is not the same as having a restorable backup. Test the restore in a separate environment and measure how long it takes. If a restore takes six hours, a one-hour maintenance window makes no sense. The full strategy is covered in business data backup strategy and disaster recovery and business continuity planning.
The "go or roll back" decision point
Set in advance the criteria that make you cancel: for example, response time above a threshold, a rising error rate, or a failed consistency check. Decide who has the authority to decide, so there is no debate in the middle of the process.
Structure rollback versus data rollback
Restoring structure is easier than restoring data. Once users have written new data into the new structure, going back to the old one can mean losing that data. That is why dual writing helps so much: the old structure stays complete, so cancellation is safe until the contract stage.
Testing before the day
An untested migration is a gamble. Prepare a test environment that resembles production.
- **A copy of production data**: use a copy (with personal data masked if needed) so timing and behavior are close to reality
- **Measure duration**: record the time of each step and extrapolate for data growth
- **Test both code versions**: make sure the old and new versions run well on the mixed structure
- **Rehearse the execution**: run the whole procedure from start to finish, including the rollback
- **Automated tests**: put migration scripts into the continuous integration flow, as discussed in [automated testing and CI/CD](/blog/pengujian-otomatis-dan-ci-cd-untuk-aplikasi-bisnis)
- **User acceptance testing**: involve business users to check reports and key figures after the trial, in line with [UAT before an app launches](/blog/uat-pengujian-sebelum-aplikasi-diluncurkan)
Big migrations: changing database engine or provider
Moving a database to a different engine (for example from a local server to a managed cloud service, or from one database type to another) is a category of its own. The usual pattern:
- **Continuous replication**: run the new database as a replica that always catches up with the old one
- **Parallel verification**: compare the results of important queries on both databases for several days
- **A short cutover**: at the chosen moment, pause writes briefly, confirm the replica is identical, then switch the application to the new database
- **A standby period**: keep the old database in read-only mode for a while as a way back
- **Application adjustments**: check behavioral differences (result ordering, time handling, case sensitivity) that can trigger subtle bugs
Strategic considerations and the danger of dependence on one provider are discussed in vendor lock-in in cloud and business software. For moving a whole system, including data, see also preparing data migration to a new system and modernizing legacy systems without stopping operations.
When a maintenance window is actually better
Zero downtime is not an absolute goal. For some businesses, a planned maintenance window is cheaper and safer than a complicated gradual design.
- Internal applications used only during working hours, with quiet weekends
- Small changes that need only minutes on small tables
- A very complex one-off migration, where the risk of errors in the dual pattern outweighs the benefit
- Businesses with clear closing hours, such as a store that closes at night
What matters is that the window is announced, short, and backed by a rollback plan. Avoid sudden maintenance without notice on peak sales days. Sync with the business calendar: avoid month-end close, payday, and promotion season.
Collaboration between business and technical teams
Database migration is often treated as a purely technical matter, yet its success depends on coordination.
- **Business process owners** name the reports and figures that must remain correct after migration
- **The technical team** explains risks, duration, and options in understandable language
- **Customer support** is prepared for questions if there is a brief disruption
- **Data owners** approve consistency criteria, for example that total balances must match exactly
- **Documentation** records what changed, why, and how to go back, supporting [technical documentation and project handover](/blog/dokumentasi-teknis-dan-serah-terima-proyek-software)
If database performance is the reason for the migration, also review slow database and business application performance, because the problem can often be solved with better indexes or queries without a big migration.
A short checklist before running a migration
- A recent backup exists and its restore has been tested
- The migration script has run on a copy of production data and its duration is known
- Old and new code versions are compatible with the structure during the transition
- A written rollback plan with criteria and an owner
- Monitoring is ready: response time, error rate, database load
- The schedule has been communicated to users and customer support
- The post-migration consistency checks are defined
- The team is on standby during and after execution
Frequently asked questions
Can every migration be done without downtime?
Not every one. Many changes can be made gradually, but some need a brief pause, for example the final cutover to a new database engine. The target is the shortest possible planned pause.
How long should the old structure be kept before deletion?
Long enough to be sure no report, integration, or script still uses it, usually a few weeks up to one financial close cycle. Monitor usage before deleting.
Do we need to change the application just for the migration?
Often yes, at least to be compatible with two structures during the transition. The team should include this work in the estimate rather than treat it as free.
What if the migrated data turns out to be inconsistent?
That is what consistency checks and the standby period are for. If a difference is found, stop the cutover, fix the source of the problem, and repeat. The quality of old data also needs checking; see data quality and data governance.
Conclusion
Changing a database in use is a matter of discipline, not bravery. With the expand-migrate-contract pattern, moving data in small chunks, tested backups, and rehearsals on a copy of production data, a big change can be broken into small safe steps. If zero downtime is not possible, make a maintenance window that is short, announced, and has a way back.
Plan database changes without disrupting operations
Agsora helps design and carry out database migrations and business application modernization in stages, with testing and a clear rollback plan. Tell us about your current system to get an initial outline.
Free ConsultationRecommended for you
Reading related to this topic
Load Testing: Stress-Testing Your Online Store and Apps Before Big Promos and Peak Season
A load testing guide for businesses: test types, setting targets from data, realistic scenarios, percentile metrics, fixing bottlenecks, and a peak-day plan.
SPF, DKIM, and DMARC: Keeping Business Email Delivered and Safe from Domain Spoofing
How SPF, DKIM, and DMARC work, inventorying email sources, a gradual rollout, separating transactional and marketing email, and the deliverability indicators to monitor.
Feature Flags and Gradual Rollouts: Releasing New Business App Features with Lower Risk
The feature flag concept, its four types, gradual rollout patterns, monitoring indicators, relation to testing and mobile apps, risks, and steps to start.
Free checklist: choosing a software house
24 points to evaluate a vendor before you sign. Can be saved as a PDF.
Ready to build a system that grows with your business?
Discuss your needs with the AG·SORA team, no cost, no commitment.