Migrate a Website Between Servers with Zero Data Loss

Khimananda Oli 7 min read Database
Migrate a Website Between Servers with Zero Data Loss

By Khimananda Oli | Last reviewed: August 2026

Server migrations fail when teams treat them as simple file copies rather than state synchronization problems. To migrate a website between servers with zero data loss, you must synchronize the filesystem, freeze database writes during the final cutover, and manage DNS propagation explicitly. This disciplined approach prevents the orphaned records and missing assets that plague ad-hoc transfers. If you are moving from shared hosting or an outdated VPS, reviewing migration strategies for cloud transitions provides essential context before executing these steps.

Source ServerFiles + DBDestinationStaging Envrsync + mysqldumpDNS
Migration overview: Data synchronizes horizontally while DNS remains pointed at source until validation completes

How do you prepare a server environment before migrating a website?

Most data loss occurs because the destination environment differs subtly from the source. Before transferring a single byte, you must replicate the exact runtime configuration. This includes PHP versions, Nginx/Apache modules, system libraries, and user permissions. A mismatched php.ini or missing ImageMagick library won't stop the transfer, but it will corrupt functionality post-cutover.

Audit and replicate source configuration

  • Capture installed packages: On Debian/Ubuntu source servers, run dpkg --get-selections > packages.txt. On RHEL/CentOS, use yum list installed > packages.txt.
  • Export PHP/runtime config: Copy /etc/php/8.3/fpm/php.ini, pool configs, and any custom extensions. Do not rely on defaults.
  • Document cron jobs and services: Run crontab -l for every application user. Export systemd unit files if you use custom services.
  • Verify disk and inode capacity: Ensure the destination has at least 20% more space than current usage. Check inodes with df -i; many migrations fail because files fit but inodes exhaust.

For teams adopting infrastructure-as-code, defining this environment in Terraform or Ansible eliminates drift. My practical Terraform guide covers provisioning identical staging environments that serve as safe migration targets.

What is the safest method to transfer files without corruption?

rsync remains the industry standard for file transfer because it supports delta synchronization, permission preservation, and verification. Avoid scp or FTP for production migrations; they lack resume capability and integrity checks. The critical flags are -avzHAXS: archive mode, verbose, compression, hard-links, ACLs, extended attributes, and sparse file handling.

# Initial bulk transfer (run days before cutover)
rsync -avzHAXS --progress \
  --exclude='.env' \
  --exclude='storage/logs/*' \
  --exclude='node_modules/' \
  /var/www/site/ user@dest-server:/var/www/site/

# Verify integrity after transfer
ssh user@dest-server "find /var/www/site -type f -exec md5sum {} \; > /tmp/dest_checksums.txt"
find /var/www/site -type f -exec md5sum {} \; > /tmp/source_checksums.txt
diff /tmp/source_checksums.txt /tmp/dest_checksums.txt

The --exclude flags prevent overwriting environment-specific configurations and transient logs. Always exclude .env files; these contain credentials unique to each server. Generate checksums on both sides and diff them. If any hash mismatches, re-run rsync for those specific paths. This verification step is non-negotiable for claiming zero data loss.

How do you migrate databases with full transactional consistency?

File transfers are forgiving; database migrations are not. Copying raw MySQL/MariaDB data directories while the service runs guarantees corruption. You must use logical dumps with proper locking or physical backups from stopped replicas. For PostgreSQL, use pg_dump with --format=custom for parallel restore capability.

1. Freeze WritesMaintenance Mode2. Consistent Dump--single-transaction3. Secure Transferrsync + checksum4. Restore & VerifyRow count checkNever copy live datadir
Safe database migration requires sequential write-freeze, logical dump, verified transfer, and row-count validation

MySQL/MariaDB safe export procedure

  1. Enable maintenance mode in your application to halt new writes. For Laravel, run php artisan down --retry=60.
  2. Dump with transactional consistency:
    mysqldump --single-transaction --routines --triggers \
      --set-gtid-purged=OFF --quick \
      -u root -p production_db > /backups/prod_$(date +%F).sql
    The --single-transaction flag ensures InnoDB tables dump consistently without global locks. Add --master-data=2 only if setting up replication.
  3. Compress and transfer: Pipe through gzip before rsync to reduce transfer time by 70–90%.
  4. Restore and validate: After importing, compare row counts per table between source and destination. Use SELECT COUNT(*) FROM table_name; on both servers. Matching counts don't guarantee correctness, but mismatches guarantee failure.

If your application cannot tolerate even brief write freezes, configure read replicas and promote them on the destination. This adds complexity but enables true zero-downtime database migration. For most SMB workloads I manage in Nepal and globally, a planned 5–10 minute maintenance window with proper communication outperforms complex replication setups.

How should you manage DNS TTLs to prevent traffic loss during cutover?

DNS propagation is where "zero data loss" migrations silently fail. Users hitting the old server after you've frozen writes creates lost orders, failed logins, and corrupted sessions. Lower your DNS TTL to 300 seconds (5 minutes) at least 48 hours before migration. This ensures resolvers refresh frequently during your cutover window.

TTL ValuePropagation TimeUse CaseRisk Level
86400 (24h)Up to 24 hoursStable production (default)High during migration
3600 (1h)Up to 1 hourPre-migration (1 week prior)Moderate
300 (5m)5–10 minutesCutover windowLow (recommended)
60 (1m)1–2 minutesEmergency rollbackHigher query load

After updating the A/AAAA record to the destination IP, monitor DNS resolution globally using tools like dig @8.8.8.8 yourdomain.com or public DNS checkers. Keep the source server running and accepting traffic for at least 2× your previous TTL duration. Only decommission the source after confirming zero requests in access logs for that period. If you're also implementing SSL on the new server, follow Let's Encrypt setup best practices to avoid certificate warnings during the transition.

What validation checklist confirms a successful migration with zero data loss?

Assuming success because the site loads is professional negligence. Systematic validation catches silent failures before users do. Create a written checklist covering functional, data, and performance dimensions.

Source Baseline✓ File checksums✓ DB row counts✓ Response times✓ Error rate <0.1%✓ Cron execution✓ Email deliveryDestination Verified☐ Match checksums☐ Match row counts☐ ≤10% slower☐ Error rate <0.1%☐ Cron confirmed☐ Test emails sent
Validation requires matching every baseline metric from source against destination before accepting the migration

Critical verification steps

  • Checksum parity: Every file transferred must have identical MD5/SHA256 hashes. Automate this; manual spot-checks miss edge cases.
  • Database row counts: Script comparisons for all tables. Investigate any discrepancy immediately—don't assume it's "just cache."
  • Functional smoke tests: Execute core user journeys (login, checkout, form submission) on the destination via its IP address using Host header overrides before DNS switches.
  • Performance baselines: Compare p95 response times. A 3× slowdown indicates misconfigured caching, missing indexes, or resource constraints.
  • Outbound connectivity: Test email sending, API webhooks, and third-party integrations. New servers often have different egress firewall rules or SMTP restrictions.
  • Scheduled tasks: Confirm crons executed at expected times. Check logs, not just configuration files.

Document every validation result. For compliance-focused environments (SOC 2, ISO 27001), this evidence demonstrates controlled change management. Teams deploying Laravel applications should pair this with zero-downtime deployment tooling to automate future releases post-migration.

Migrate a Website Between Servers with Zero Data Loss: Final Checklist

Successful migration isn't about speed—it's about predictable outcomes. Lower DNS TTLs early, verify every transfer with checksums, freeze writes during database exports, and validate systematically before accepting traffic. The extra hours spent on preparation save days of incident response. If your team lacks bandwidth for rigorous validation or needs audit-ready documentation for compliance frameworks, reach out to discuss your migration requirements. Production systems deserve methodical execution, not hopeful guessing.

Frequently Asked Questions

Compare source and destination file checksums using rsync with the checksum flag. Validate database integrity by comparing row counts and running CHECK TABLE commands on both servers before switching DNS records to confirm complete accuracy.

Use Percona XtraBackup or mysqldump with single-transaction and quick flags for InnoDB engines. This creates a consistent snapshot without blocking write operations, ensuring active applications continue functioning during the export phase of your server migration process.

Yes. Deploy code to the new server first, sync files via rsync, import the database, test thoroughly using hosts file overrides, then update DNS TTL to sixty seconds before the final cutover to minimize propagation delays effectively.

Lower MX record TTL forty-eight hours prior. Configure the new mail server identically, test delivery, then update DNS. Monitor queues on the old server for seventy-two hours to catch stragglers before decommissioning legacy infrastructure completely.

Use archive mode, compression, partial transfers, and checksum verification flags together. This preserves permissions, resumes interrupted transfers safely, and validates every byte transferred matches the source exactly, which is critical for achieving zero data loss guarantees.

Retain the old server for at least seven days. This covers full business cycles and allows rollback if hidden issues emerge post-cutover while DNS fully propagates globally across all recursive resolvers and client caches.

No. Copy existing certificate and private key files to the new server. Only generate new certificates if you are simultaneously changing domain names or if current certificates expire within thirty days of your planned migration window.

Export crontabs using crontab -l on the source server. Import them on the destination, but disable execution until the final cutover. Enable immediately after DNS switch and monitor logs to confirm all scheduled tasks execute correctly without duplication or gaps.

User and group IDs often differ between servers. Run chown recursively to match the web server user on the destination. Verify ACLs and SELinux contexts if applicable, as these security layers frequently break functionality after raw file transfers.

Edit your local hosts file to point the domain to the new server IP. Test all functionality including forms, payments, and API endpoints. This validates the complete environment without affecting live traffic or requiring premature DNS changes.

Replication provides near-realtime synchronization and shorter cutover windows compared to traditional dumps. Configure primary-replica topology, let it sync fully, then promote the replica. This approach minimizes maintenance windows significantly for high-traffic production databases requiring continuous availability.

Keep all URLs identical and maintain the same robots.txt and sitemap.xml files. Verify canonical tags remain unchanged. Submit the new server IP in Google Search Console only if changing hosting providers to help search engines reassociate content correctly.

Throttle rsync transfers to avoid saturating network links which causes packet loss and corrupted transfers. Schedule bulk data movement during off-peak hours. Use dedicated transfer networks or VPN tunnels when migrating sensitive data across untrusted public internet connections.

Never commit secrets to version control. Transfer .env files and credentials via encrypted SCP or vault systems. Validate configuration values against the new server paths and service endpoints immediately after transfer to prevent runtime failures in production environments.

Track error rates, response times, and transaction volumes on both servers during transition. Set up log aggregation to compare request patterns. Alert on any anomalies indicating missing assets, broken database queries, or authentication failures that signal incomplete data transfer.