Magento 2 is the most resource-demanding platform among popular e-commerce engines. Three things complicate a move: strict version requirements for PHP and Elasticsearch, the app/etc/env.php file with server path bindings, and the mandatory catalog reindex after the move.
Magento 2 requirements for the new server
Before the move, check the component versions — a mismatch in even one breaks the installation:
| Component | Magento 2.4.6 | Magento 2.4.7 |
|---|---|---|
| PHP | 8.1-8.2 | 8.2-8.3 |
| MySQL | 8.0 | 8.0 |
| Elasticsearch / OpenSearch | 7.17 | 7.17 / 2.12 |
| Redis | 6-7 | 6-7 |
If the PHP version on the new server is higher than supported, composer install fails with a dependency error before the site even starts.
Moving files and the media library
The pub/media directory with product images is often heavier than the Magento code itself, so transfer it with a separate rsync run using the resume flag so an interrupted transfer does not start over:
rsync -avz --partial --progress /var/www/magento/pub/media/ user@newserver:/var/www/magento/pub/media/
General techniques for rsync, SCP and FTP are covered in the article moving site files. There is no need to move the var/cache, var/page_cache and generated directories — Magento rebuilds them.
Exporting and importing the database
The Magento database is usually large because of log tables and cart quotes, so before exporting clean up old logs with bin/magento setup:cleanup:logs, then take a dump:
mysqldump -u magento_user -p --single-transaction magento_db | gzip > magento_backup.sql.gz
On the new server, unpack and import the dump:
gunzip magento_backup.sql.gz
mysql -u magento_user -p magento_db < magento_backup.sql
The general algorithm for moving MySQL, including large databases, is in the article moving a MySQL database.
Configuring env.php and cron
The app/etc/env.php file stores not only database connection settings but also absolute paths for the cache, sessions and queues. After the move, update the db block and check the cache section — if the disk paths differ, Magento cannot find the file cache and returns a 500 error on the very first page.
bin/magento setup:upgrade
bin/magento cache:flush
Magento relies on cron jobs for message queues and scheduled price updates, so add a job to the web server user's crontab:
* * * * * /usr/bin/php /var/www/magento/bin/magento cron:run 2>&1 | grep -v "Ran jobs by schedule"
Reindexing the catalog after the move
After importing the database, Magento's indexes are considered stale even when the data has not changed. Switch indexing to schedule mode and run a full reindex manually:
bin/magento indexer:set-mode schedule
bin/magento indexer:reindex
Skip this step and the catalog shows wrong prices, stock levels and search results. Reindexing a catalog of 50,000 products takes 10 to 30 minutes depending on server power.
Testing before the DNS switch
Open the store on the new server by IP, overriding the host in the local /etc/hosts file, and test checkout, applying a coupon and loading images from pub/media. Lower the domain's A record TTL to 300 seconds a day before the switch — this lets changes propagate faster across DNS providers. A detailed scheme for a switch without downtime is in the article switching hosting without downtime.
Magento 2 migration checklist
- PHP, MySQL and Elasticsearch versions match the release requirements.
- The pub/media directory is moved in full, var and generated are rebuilt.
- The env.php file is updated: database connection and cache paths are correct.
- The cron:run job is added to the crontab on the new server.
- The full catalog reindex ran without errors.
- Checkout was tested on the new server by IP.
After switching the domain, go through the general checklist in the article post-migration site checklist.