Sometimes you need to change text everywhere in a WordPress site: an old domain after a migration, http:// to https://, a changed upload path, a renamed company, or an outdated email address. Doing this in the database is fast, but there’s one trap that breaks sites: serialized data.

Why raw SQL REPLACE is dangerous

WordPress and plugins store arrays and objects as serialized PHP strings, which include each string’s length:

a:1:{s:3:"url";s:22:"http://old-example.com";}

If you replace http://old-example.com (22 characters) with https://new-example.com (23 characters) using SQL REPLACE(), the stored length s:22 no longer matches. PHP then can’t unserialize the value, and widgets, theme options or plugin settings silently reset or disappear.

Tools that understand serialization fix the lengths for you. Use them.

cd /var/www/example.com

# preview what would change
wp search-replace 'http://old-example.com' 'https://new-example.com' --all-tables --dry-run --report-changed-only

# do it
wp search-replace 'http://old-example.com' 'https://new-example.com' --all-tables --precise

# then clear caches
wp cache flush

Useful options:

Option Purpose
--dry-run Show counts without changing anything
--all-tables Include non-prefixed and plugin tables (default: only WordPress-registered tables)
--precise Use PHP for every row: slower, but handles tricky serialized data
--skip-columns=guid Leave post GUIDs alone (the default for domain changes is debated; GUIDs shouldn’t normally change on a live site)
--include-columns=post_content Limit to specific columns
--regex Use a regular expression (careful)
--export=file.sql Write a modified SQL dump instead of changing the live database
--network All sites in a multisite network

Always back up first: wp db export before-replace.sql. See WP-CLI guide.

Method 2: plugins

If you don’t have shell access:

  • Better Search Replace: select tables, dry run, serialization-safe.
  • Search & Replace and similar tools work the same way.

On large databases, plugins can time out, because they run inside PHP requests. WP-CLI has no such limit.

Method 3: during migration

Migration tools (Duplicator, WPvivid, All-in-One WP Migration) run a serialization-safe replace automatically when you restore to a new URL. Check their logs.

Common replacements

Task Search → Replace
Domain move https://old.com → https://new.com
Force HTTPS in content http://example.com → https://example.com
Staging to live https://staging.example.com → https://example.com
CDN removal https://cdn.example.com/wp-content → https://example.com/wp-content
Email change [email protected] → [email protected]

Tips:

  • Don’t include a trailing slash in the search term unless you mean it.
  • Run separate passes for http://, https:// and protocol-relative //old.com variants if the content mixes them.
  • Page builders (Elementor and others) may cache CSS with old URLs. Regenerate their CSS and files afterwards (Elementor → Tools → Regenerate files and data).

When raw SQL is OK

For columns that never hold serialized data, such as post_content in wp_posts, raw SQL is fine:

UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://old.com', 'https://new.com');

But wp_options, wp_postmeta, wp_usermeta and many plugin tables do contain serialized values. Use WP-CLI for those.

After the replace

  1. Flush all caches: object cache, page cache plugin, Nginx FastCGI cache, CDN.
  2. Re-save permalinks (Settings → Permalinks → Save).
  3. Spot-check pages, menus, widgets and theme settings.
  4. Scan for mixed content in the browser console (on HTTPS sites).

Quick reference

Task Command
Backup wp db export backup.sql
Preview wp search-replace old new --all-tables --dry-run
Replace wp search-replace old new --all-tables --precise
Multisite add --network
Flush caches wp cache flush

Related: change the WordPress site URL and WordPress staging site.

  • WordPress
  • WP-CLI
  • MySQL