You exported your WordPress site, moved to the new host, hit Import, and got this:
Your file exceeds the upload limit set by your host web server.
You raised the limit in .htaccess. Nothing changed. You raised it again. Still nothing.
The WordPress upload limit is one of the most common walls in a migration, and the reason it is so frustrating is that there are usually two separate limits — and most advice only addresses one of them. This post covers both, explains why the standard fix silently fails on most modern hosting, and gives you four free ways through.
What this covers
- Which limit you are actually hitting
- Why editing .htaccess usually does nothing
- The second limit, inside the plugin
- Four free ways to import a site of any size
- The trap after the import: serialised data
- Migrating before DNS has switched
First: work out which WordPress upload limit you are hitting
Before changing anything, find out what your server currently allows. In WordPress, go to Tools → Site Health → Info → Server and look for:
upload_max_filesize— the largest single file PHP will acceptpost_max_size— the largest total request, which must be bigger than the abovememory_limitmax_execution_time
Write those numbers down, then compare them with your archive.
If your archive is smaller than upload_max_filesize, your server is not the problem and raising it will do nothing. Skip to the second limit below.
If your archive is larger, you are hitting a genuine server limit — keep reading.
Why editing .htaccess usually does nothing
Almost every guide tells you to add this to .htaccess:
php_value upload_max_filesize 600M
php_value post_max_size 600M
Here is what nobody mentions: that only works if your host runs PHP as an Apache module (mod_php). Most modern hosting runs PHP-FPM or FastCGI instead, and on those setups php_value directives are ignored completely — or throw a 500 Internal Server Error.
So you edit the file, save it, retry, and get the identical error. The edit was never applied.
The fix for PHP-FPM hosting
Create a file called .user.ini in your WordPress root, next to wp-config.php:
upload_max_filesize = 600M
post_max_size = 600M
memory_limit = 512M
max_execution_time = 300
Two things to know:
- Changes take up to five minutes. PHP caches
.user.inifor 300 seconds by default, so an immediate retry shows the old value and makes you think it failed again. - Verify before retrying. Go back to Site Health → Info → Server and confirm the numbers actually changed. If they did not, your host is enforcing the cap above PHP and only they can raise it.
Other places the limit can live
- Your hosting control panel. cPanel has MultiPHP INI Editor; Plesk has PHP Settings.
- A
php.inifile in your WordPress root, which works on some configurations. - Ask your host. A ticket asking them to raise the limits for a migration is routine and usually actioned quickly.
Note that raising PHP limits does not help if there is an Nginx layer in front, which enforces its own client_max_body_size. Only your host can change that.
The second upload limit: the one inside the plugin
Here is the part that catches out even experienced developers.
All-in-One WP Migration’s free version caps imports at 512MB — regardless of your server settings. Exports are unlimited, which is exactly why this surprises people: the export runs perfectly, produces a 900MB file, and then refuses to import it on the other side.
You can raise upload_max_filesize to 4GB and it will make no difference. The check is inside the plugin, not on your server. That is also why the official answer is the Unlimited Extension at $69/year.
The constants.php edit, and why it stops working
You will find guides telling you to edit the plugin’s own source:
define( 'AI1WM_MAX_FILE_SIZE', 536870912 * 10 );
This does work. It is also not a fix, for one simple reason: the file is overwritten every time the plugin updates. Your migration works today, the plugin auto-updates next month, and the limit is back. If you manage sites for other people, you have just left a trap for whoever touches it next.
Four free ways to import a site of any size
1. Export without the media library, then move uploads by FTP
The most reliable free method, and it works at any size.
- Run the export with the media library excluded. The archive drops to a fraction of its size, usually well under any limit.
- Import that archive normally.
- Connect over SFTP and copy
wp-content/uploadsfrom the old server to the new one.
Two steps instead of one, and you need FTP access, but there is no size ceiling and it costs nothing.
2. Use a plugin that chunks the upload
The upload limit applies to a single request. If the archive is sliced into small pieces in the browser and reassembled server-side, no individual request is ever large enough to hit the limit — so the limit stops mattering, whatever it is set to.
This is the approach Open Migration takes. It is free and GPLv2 with no paid tier, and it picks the chunk size automatically from your server’s own reported limits. It also rewrites URLs, server paths and the database table prefix during the restore, including inside serialised data — more on why that matters below. The full documentation walks through each step.
Disclosure: I build and maintain Open Migration.
3. Use Duplicator
Duplicator’s free version has no import size cap either. It works differently — you upload an archive plus an installer.php script over FTP and run the installer in your browser, outside WordPress. More hands-on, but free and effective.
4. Ask your new host to migrate for you
Frequently overlooked, and often the fastest option. Many hosts will migrate your site free to win your business. If you are moving hosts anyway, ask before doing any of the above.
The trap after the import: serialised data
Getting the file uploaded is only half a migration. The other half is that your old domain and server paths are written all through the database, and not just in Settings.
Themes and page builders store configuration as PHP-serialised arrays, which record the length of every string:
s:29:"https://oldsite.com/wp-content";
That s:29 is the character count. Run a plain SQL find-and-replace, change the domain to something shorter or longer, and the count no longer matches. PHP can no longer unserialise the value and it is silently discarded — which is why a migrated site often loads but with broken widgets, missing theme options, or a page builder that has forgotten its layout.
Any tool you use must unserialise, replace, then re-serialise. Options that do this correctly:
- WP-CLI:
wp search-replace 'oldsite.com' 'newsite.com' --all-tables - Better Search Replace, a free plugin
- A migration plugin that handles it as part of the restore
Never run a raw UPDATE ... REPLACE() query against wp_options or wp_postmeta.
If you are migrating before DNS has switched
Most real migrations happen while the domain still points at the old host, so you work through a temporary address. Do it in this order:
- Import onto the temporary address and confirm the site works there.
- Point your DNS at the new server and wait for it to resolve.
- Only then change the site address in the database.
Changing the address before DNS resolves leaves the site unreachable at both addresses. This step cannot be automated by any plugin, because WordPress only ever sees the hostname a visitor requested — it has no way of knowing DNS was switched.
Frequently asked questions
Why is my export bigger than my site?
Exports often include caches and other plugins’ backup folders. Excluding wp-content/cache and any updraft or ai1wm-backups directories can cut the archive dramatically.
Is there a size at which none of this works?
Not really. Once uploads are chunked or moved by FTP, the practical limit is disk space — the server needs room for the archive alongside the site itself.
Do I need to change URLs manually after importing?
Not if your tool handles serialised data. If you used a plain search-replace, check your theme options and page builder layouts before assuming it worked.
Why am I logged out at the end of an import?
Restoring the database replaces the destination’s user accounts with the source site’s. Log back in with the original site’s username and password.
Summary
If you are stuck on an upload limit, check in this order:
- Compare your archive size against
upload_max_filesizein Site Health. - If the archive is smaller, the cap is in your plugin, not your server.
- If it is larger, use
.user.inirather than.htaccess— and verify the change applied. - If nothing moves the limit, use a method where the limit does not apply.
The size limit is the visible problem. Serialised data is the one that quietly breaks sites a week later — so whatever route you take, make sure your search-replace is doing it properly.
