I wrote an article two years ago on how to move your WordPress website, which has been one of my most popular posts.
Over the past two years I’ve found some improvements to my process, most notably around serialized arrays.
Before Migrating, Custom Table Prefix
When building a new website, make sure to use a custom table prefix (you define this in wp-config.php). If you started with an existing database, use this process to change the prefix.
I like to make mine
[clientname][date]_. So if my client was Automattic and I built the website today, the prefix would be
This is so that there’s no risk you upload your tables to a database with the same named tables. When working on an existing site, it’s important to have both sets of tables in the database so that if there’s any issues with the migration, you can quickly switch back to the old site while you figure out the issue.
- Backup the database tables. I like to use Sequel Pro to connect to my database and export them, but you can also use the Adminer WordPress plugin or phpMyAdmin through your server’s cPanel. The default export will the a .sql file, but you might want to use one of the compressed formats. Many hosts only allow you a small file upload (like 2MB), and compressing it can help you stay under that limit.
- Backup the wp-content directory. This can be as easy as FTP’ing onto your server and dragging a copy of wp-content/ to your computer. If you have SSH access and are comfortable with command line, I like to make a tarball because it is much faster to download than a lot of small files. Use a command like this:
tar -pvczf wp-content.tar.gz wp-content/.
- Upload the database to the new server. If WordPress is already installed, use the Adminer plugin to add the database. If not, you might use phpMyAdmin provided by the host.
- Upload searchreplacedb2.php to the top level of your server (wherever wp-config.php is). This is used to find all the uses of the old domain and replace them with the new domain. The reason we’re using this tool instead of simply doing it in the database is that it will work with serialized arrays. Click the above link to read more about the problem and solution. If you’re really worried about security, do this locally or on your development server so that this file never has to be on the production server.
- Load the the search and replace tool at http://www.yoursite.com/searchreplacedb2.php. It will auto-populate the database information from wp-config.php. Click “Next”, select the applicable tables, then on the find/replace screen type the old and new domain. Make sure you do not include a trailing slash (correct = http://www.yoursite.com | incorrect = http://www.yoursite.com/). Do the find and replace, then remove this file from your server.
- If a brand new website, upload copy of WordPress along with your custom wp-content directory. If there’s already a WordPress website live, follow the rest of the steps below.
- On your computer, unpackage the wp-content tarball (if you tarballed it), and then rename the folder wp-content.new. The name doesn’t matter, it just has to be different than wp-content. Upload the folder to the same directory that has the old wp-content/ .
- Open wp-config.php. Find the line that starts with $table_prefix. Comment it out, and create a new $table_prefix line with your custom table prefix. It will look something like this.
- Save wp-config.php, and then immediately rename wp-content/ to wp-content.old/, and wp-content.new to wp-content/
- Check the website’s homepage. If anything looks wrong, switch to the old site while you figure it out. Go into wp-config.php, comment out the new table prefix and remove the commenting on the old table prefix. Rename the wp-content directories back to how they were.
- If the site is working, log in and go to Settings > Permalinks, then click Save. This will update the permalink structure and ensure all URLs work.
- Go to Settings > Privacy and make sure you have the site visible to search engines. I use the WordPress SEO plugin which has a big red nag on the backend if you’re privacy settings aren’t set correctly. Since I don’t want that nag showing up on my dev environment, I include this snippet in my functionality plugin (line 150-159) to hide it under certain conditions (localhost or master-wp in the domain, since those are where I develop).
- On the old site, install the Migration Notice plugin. I’ve had a lot of clients get confused about which backend they are supposed to post new content to, so if you aren’t deleting the dev environment immediately this prevents that issue.
- Make sure you’ve removed searchreplacedb2.php. This was mentioned in #4, but deserves reiterating (thanks WPExplorer).
- Update file permissions of wp-content directory. If you’re using WPEngine, they’ve added a super useful button “Reset File Permissions” in their WPEngine page of your WordPress backend.