How to Migrate Your Website to a New Host Without Losing Data
You migrate a website to a new host without losing data by copying the files, exporting and re-importing the database, and then switching the DNS only after you have verified the new environment. The process is mechanical, and if you follow it in the right order, you can avoid downtime, broken links, and corrupted data. The key is to treat the migration as a data transfer with verification steps at every stage, not as a single cut-over event.
How to migrate website to new host without losing data: the three-layer copy
Your website is not one thing. It is three layers that need to move together: the static files (HTML, CSS, JavaScript, images, and any uploaded content), the dynamic application code (PHP, Python, or similar), and the database (typically MySQL or PostgreSQL). Each layer has its own transfer method, and each must be verified independently before you touch DNS. Start by taking a full inventory. Log into your current host and list every directory under your web root, including hidden files like .htaccess or .env. Miss one of those and your site will run but behave differently, often with broken redirects or missing environment variables.
For the file transfer, use rsync over SSH. It is the safest tool because it checksums each file and only moves what has changed, which means you can run it repeatedly without harming your data. The command below copies everything from your old host to the new one, preserving permissions and ownership. Replace the placeholders with your actual paths and user names.
rsync -avz --progress --delete \
user@old-host:/var/www/html/ \
user@new-host:/var/www/html/
The --delete flag is important. It removes files on the new host that do not exist on the old one, which prevents stale files from lingering after a second run. Run this command once as a dry run with --dry-run to see what it will do, then run it for real. If you are moving across a slow connection, add --partial so an interrupted transfer can resume.
Export and import the database with a consistent snapshot
Files are easy. The database is where most migrations fail. The danger is that your site writes to the database while you are exporting it, producing a snapshot that is internally inconsistent. To avoid that, you must lock the tables during the export. The standard tool is mysqldump with the --single-transaction flag, which gives you a consistent snapshot without locking the entire server for writes. Run the dump on the old host and pipe it directly to the new host over SSH, so you never write a large SQL file to disk on the old server.
mysqldump --single-transaction --quick -u dbuser -p dbname | \
ssh user@new-host "mysql -u dbuser -p newdbname"
You will be prompted for the password on both ends. After the pipe completes, verify the row counts on both sides. Do not trust the exit code alone. Run a query on the new host that counts rows in your largest table, and compare it to the same query on the old host. For example:
mysql -u dbuser -p -e "SELECT COUNT(*) FROM wp_posts;" newdbname
If the numbers match, move on. If they differ, re-run the dump after stopping writes to the old site. You can do that by putting the old site into maintenance mode, which is a small file in the web root that returns a 503 status to visitors. The important detail is to export the database after you have copied the files, because some applications store absolute file paths in the database, and you will need to update those paths in the SQL dump before importing.
Update configuration files and search for hard-coded URLs
After the files are on the new host and the database is imported, your site will still be broken until you fix the configuration. Most applications have a single config file that holds the database connection details and the site URL. For a typical PHP application, that is wp-config.php for WordPress or config.php for others. Edit that file on the new host to point at the new database name, user, and password. Also update the siteurl and home options if they are stored in the database, which they often are. You can do that with a SQL command that replaces the old domain with the new one.
UPDATE wp_options SET option_value = REPLACE(option_value, 'http://old-domain.com', 'http://new-domain.com') WHERE option_name IN ('siteurl', 'home');
But that only covers the obvious settings. Your content will have links, image paths, and internal references that point to the old domain. You need to sweep the entire database for the old domain and replace it with the new one. The safest way is to export the database to a text file, run a search and replace using a tool like sed or a dedicated script that handles serialized data, and then import the modified file. Be careful with serialized arrays, which are common in WordPress. A naive text replacement will corrupt them because the string lengths are stored in the data. Use a script that updates those lengths, or use the search and replace functionality built into your database admin tool if it handles serialization correctly.
Test the new host in isolation before switching DNS
You do not need to switch DNS to test. Edit your local /etc/hosts file or use a browser extension to point your domain at the new host’s IP address. That way you see the site exactly as a visitor would, but only from your machine. Run through the critical paths: the home page, a product page, a login, a search query, and any form submission. Check that images load, that links go to the correct URLs, and that the database connection works. Also test the admin panel, because that uses a different set of routes and often reveals path issues that the public site does not.
While you are testing, verify the email configuration. If your site sends mail, the new host may use a different mail server or require different SMTP credentials. Update the mail settings in your application and send a test message to yourself. Also check that any cron jobs or scheduled tasks are transferred. They are often stored in the old host’s crontab, not in your files, so you need to export them with crontab -l and re-import them on the new host.
Cut over DNS and keep the old host as a fallback
Once your local tests pass, you are ready to switch. Update the nameservers or the A record for your domain to point at the new host. DNS propagation takes time, so do not delete anything from the old host for at least 48 hours. If you see errors after the switch, you can change the record back and you have lost nothing. During the propagation window, some visitors will hit the old host and some will hit the new one. To avoid them seeing different content, keep the old site live and do not make changes to it. The database on the old host will be stale, but that is acceptable for a short window. If you need to accept orders during that time, you can run a one-way sync from the new host back to the old host, but that is only necessary for high-traffic commerce sites.
After the TTL has expired and you are confident that all traffic is going to the new host, do a final backup of the new environment. Then, and only then, cancel the old hosting account. Keep a copy of the old site’s files and database dump on your local machine for a month, because you will likely discover a missing file or a stale link that you want to reference. The whole process, done carefully, takes a few hours. The risk is not in the transfer itself, it is in skipping the verification steps. Do every check, run every query, and test every page. That is how you migrate a website to a new host without losing data.
