We've handled migrations ranging from a single VPS with one application to multi-server setups with shared databases, custom routing, and integrations that the client themselves had partially forgotten. The common thread in every migration that went badly — for us or for anyone who's told us about theirs — is that something assumed to be verified turned out not to be.
This list exists because assumptions are expensive. It's not exhaustive for every possible stack, but it covers the ground where things consistently go wrong.
Before you touch anything
The first four items happen before any configuration changes, before any data moves, before anything in the new environment is touched by production traffic.
1. Full backup of the source environment, verified. Not scheduled — done right now, manually confirmed. Check that the backup completed without errors and that at least one restore test has happened in the past 30 days. If no restore test exists, do one before the migration window opens.
2. Inventory of all running processes and cron jobs. Pull the process list, the cron table for all users (not just root), and any systemd timers. Note what runs, when, and what it touches. Cron jobs are the most common thing to forget during a migration and the most likely to cause subtle data issues 24 hours after cutover.
3. Dependency mapping for external connections. Which services does this environment call out to? Which services call into it by IP? Document both directions. IP-based allowlists on external APIs or payment processors are the second most common migration surprise.
4. Staging validation on the new environment. The new server should have run a copy of production traffic — or a realistic simulation — for at least 48 hours before the cutover window. This isn't optional. If it hasn't happened, push the migration date.
DNS and networking
5. Current TTL values on all DNS records. If the TTL on your primary A record is 3600 seconds, lower it to 300 at least 48 hours before cutover. After the migration completes and traffic looks stable, raise it back. Doing this after the migration is too late — propagation during the window will be slow and inconsistent.
6. MX records and email routing. If email for the domain passes through or originates from the server being migrated, document this explicitly. SPF records that reference the old IP need to be updated. It's a small change that frequently gets missed because email feels separate from "the server."
7. SSL certificate on the new environment. Certificate issued, installed, and tested. Don't discover that Let's Encrypt rate limits are a problem during a live migration window.
8. Firewall rules transferred and reviewed. Don't copy the old firewall rules blindly — read them. Migrations are a good time to remove rules that no longer apply. Rules that reference the old server's own IP need updating.
Data and state
9. Database replication or final sync plan. If the database will be copied during downtime, know exactly how long that copy takes. Run a timed test copy beforehand. If the copy takes longer than your maintenance window, you need a different plan — live replication, logical replication, or a staged approach.
10. Uploaded files and media. Application databases often migrate cleanly while user-uploaded files get overlooked. Identify every directory where users or the application writes files. Sync it. Sync it again closer to cutover.
11. Session state handling. If the application stores sessions in local files or memory, decide whether active sessions survive the migration or are terminated. If they're terminated, think about when that's least disruptive. If they need to survive, sessions need to move to a shared store before the migration.
12. Queue state if applicable. Background job queues — whether Redis-backed, database-backed, or file-based — need the same treatment as session state. Jobs in flight during the cutover either need to complete before the window opens or be safely re-queued on the new system.
Application configuration
13. Environment variables and secrets. These almost never live in version control. Track down every .env file, every secrets manager entry, every configuration value hardcoded outside the application code. Maintain a checklist of what needs to exist on the new server. Don't rely on memory.
14. Logging configuration. Where do application logs go on the new server? If they were shipping to a remote log aggregator using the old server's hostname or IP, that configuration needs updating. Discovering that logging broke during a post-migration incident investigation is a bad time to discover it.
15. Third-party webhook URLs. Payment processors, CI systems, monitoring services, external APIs that push events in — any that use the server's IP rather than the domain need updating. Make a list during the dependency mapping phase and keep it handy.
The maintenance window itself
16. Communication sent. Users informed with enough lead time that "enough lead time" means something to them, not just to you. If this is a B2B environment, their engineers need to know. The exact message doesn't matter. Silence does.
17. Rollback procedure documented and tested. If something is wrong two hours after cutover, what's the exact sequence of steps to revert? Who executes them? How long does that reversion take? This procedure should be written out, not in your head, and someone other than the person running the migration should have read it.
18. Monitoring in place on the new environment before cutover. Uptime checks, error rate alerts, resource usage thresholds — all configured and confirmed active before traffic moves. The first hour after a migration is the most important hour to have monitoring, and it's the hour when monitoring most often isn't set up yet.
Post-cutover verification
19. Smoke test from an external connection. Don't just check that the server responds — check it from outside your network, through the actual DNS resolution path, ideally from a different country. What you see on the local network during a migration can be misleading.
20. Check that the old server is still running. Don't decommission the source environment until you're certain the new environment is handling load correctly. The old server is your rollback. Keep it available for at least 48 hours after cutover, longer if the application is complex.
21. Confirm backup jobs are running on the new environment. First backup from the new server should complete before you stand down from the migration window.
22. Update internal documentation. IPs, hostnames, access credentials, architecture diagrams — whatever your team uses to understand the environment. The migration isn't done until the documentation reflects the new reality. This is also the point where the old server's credentials should be rotated or revoked.
A note on timing
We schedule cutover windows for Tuesday through Thursday, typically starting between 21:00 and 23:00 local time for the client's primary user base. Avoid Monday (people are catching up from the weekend and notice problems immediately) and Friday (problems discovered Friday evening mean a weekend incident). Midweek late evening tends to give the longest runway before business hours resume.
The window should be sized to handle at least twice the expected migration time plus the rollback time. If you can't get to that window, push the date. Rushing a migration because the window is too short is how migrations that should have been fine become multi-hour incidents.