An end-to-end process for lifting and shifting your LAMP stack applications to Azure
Published Jan 23 2020 08:49 PM 8,997 Views

This blog describes how to streamline the migration journey for moving OSS web applications developed on the LAMP stack using the MySQL database engine as a backend to Azure. By taking advantage of the Azure Migrate, Azure App Service Migration Assistant and Azure Database Migration Service, we simplify the migration of PHP based web applications like WordPress to managed services in Azure with minimal or no code changes.



Application overview

WordPress is one of the canonical applications developed on LAMP stack. WordPress is a popular content management system developed using PHP and the MySQL database engine. It is most associated with blogging but has evolved to support other types of web content including forums, media galleries, membership sites, learning management systems, and online stores. WordPress is used by more than 60 million websites, including 33.6% of the top 10 million websites as of April 2019.  

WordPress can be migrated to fully managed services in Azure like Azure App Services with Azure Database for MySQL to reduce total cost of ownership, improve security, benefit from elastic scaling, and improve operational efficiency.


Phases in the migration journey

Migrating to the cloud involves moving your web apps and databases, and there are different tools and techniques for each. However, the typical migration journey consists of four phases: pre-migration, migration, post-migration, and optimization.

During pre-migration, you:

  1. Discover the servers, application, and database assets.
  2. Determine application dependencies.
  3. Identify artifacts that need to be migrated together.
  4. Assess Azure target readiness.
  5. Determine the optimal target SKU.
  6. Detect database objects from the application layer that may break when migrating to managed services in Azure.
  7. Prepare the necessary fixes to apply during the post migration phase.

During migration, you migrate the application and your schema and data, as well as any other server objects (such as files, images) upon which your application depends.


During post-migration, you:

  1. Make the necessary fixes to breaking changes reported during the assessment testing (such as connection string format changes).
  2. Perform a few functional tests.
  3. Address any performance issues you may have encountered during the testing.

Finally, during optimization, you perform continuous evaluation and refinement. The goals of optimization are to:

  • Gather operational insights.
  • Fine-tune performance.
  • Reduce TCO.
  • Begin leveraging cloud native services for better business insights.
  • Improve security to meet compliance goals.

With this high-level roadmap of the migration journey in place, let’s take a look at the details associated with the process associated with migrating applications and the databases supporting them.


The first step in the migration journey is to “discover” the servers hosting the application and databases to determine if there are the dependencies that would require migrating these entities to Azure together.


You can use Azure Migrate for discovery and assessment of LAMP stack applications in your current IT infrastructure. The Azure Migrate service provides a powerful inventory, assessment, and reporting tool to simplify the migration planning process. The service performs a comprehensive assessment of Windows Servers and Linux machines to determine your level of readiness to migrate an on-premise physical or virtual machine to Azure. Azure Migrate sizes things based on performance and provides cost estimations for running on-premises computers in Azure.


For a WordPress application, it’s easy to identify the application and database servers and their respective dependencies, so for purposes of this blog post we don’t get into the detailed discovery process, but we recommend reading the Azure Migrate documentation for detailed instructions on running the tool for discovery and assessment in your environment.


Application migration

Azure App Service is an HTTP-based service for hosting web applications, REST APIs, and mobile back ends. Migrating applications to App Service is a relatively simple process that involves:

  1. Assessing your WordPress app to get a detailed report of all the technologies and frameworks used and whether they can be hosted on App Service.
  2. Downloading the Migration Assistant, which currently works with IIS version 7.5 and later.
  3. Using the Migration Assistant to:
    1. Run readiness checks and general assessment of your application’s configuration settings
    2. Migrate your application to App Service.

Assess your application

To begin the assessment, navigate to the Assess your site page, type in the public facing URL, and then select Assess:



App Service doesn’t rely on a static (and potentially outdated) list of supported technologies. Instead, App Service compares a dynamically generated list of technologies used by the site being scanned to similar lists for sites that are already hosted on App Service to generate a uniquely accurate assessment report. A positive assessment for a given technology guarantees that at least one customer on the platform is already using that technology.


Consider the following example.




Note: Use the Show more technologies detected for the site toggle to see additional detail about the technologies in use on the site.


Download the Migration Assistant

After you successfully assess your site, on the Assess your site page, select Start Migrating Now! or navigate to the Download the Migration Assistant for your .NET and PHP Apps page, and then select Download.



Run the Migration Assistant

When the download and installation is complete, start the App Service Migration Assistant.

The Migration Assistant is a local agent that performs a detailed assessment and then walks you through the migration process. The tool performs readiness checks as well as a general assessment of a web application’s configuration settings.



After the readiness checks are complete, review the Assessment Report, considering any warnings and resolving any errors that may have been identified. When the Assessment Report for the application shows no Errors, the Migration Assistant walks you through the process of authenticating with your Azure subscription and then prompts you to provide details of the target account, together with other configuration details for the newly migrated site.


When you have entered the appropriate detail, select Migrate, and the Migration Assistant then moves your site to the target application in App . In addition, if you use custom domains, you will need to migrate your active DNS name to Azure App Service manually as documented here.


Note: While using Migration Assistant, make sure not to choose Hybrid connection option as we plan to migrate database in the next step.


Supported configurations

The Migration Assistant is designed to migrate most modern ASP.Net and PHP applications, but it does not support all configurations. For more details about what the tool supports, together with workarounds for some unsupported sites, see the App-Service-Migration-Assistant wiki in GitHub. You can also find more details about App Service migrations on the App Service Migration checklist.


Database migration

While the Migration Assistant is designed to migrate web applications and their associated configurations, it will not migrate the MySQL databases. For migrating MySQL databases to Azure Database for MySQL, you can choose to perform migration using dump and restore.


Identify the right pricing tier for your target Azure Database for MySQL server

It’s critical to identify minimum required pricing tier for the target Azure Database for MySQL to ensure that you have an optimal post migration experience. The Basic tier for Azure Database for MySQL is generally used for development and demo purposes where performance of the MySQL databases is not critical. For all other scenarios including production scenarios, using General Purpose or Memory Optimized tiers for Azure Database for MySQL servers are recommended.


The compute tier of the server can be scaled up or down on-demand while storage tier can be scaled up only. When deciding the storage tier for the server hosting the database, it is important to choose the storage tier not just based on the absolute size of your database but also based on the IOPs requirements of your workload. General Purpose and Memory Optimized tiers provisions 3 IOPs per GB of storage allocated. For instance, to get performance at par with your current on-premises deployment. It is generally recommended to keep the compute tier same or higher than your existing environment. For example, if you are running on a 4 CPU/20GB server in our current environment, it is recommended to at least start with 4 vCore General Purpose or Memory Optimized tier to achieve optimal performance.


During Migration, the compute tier may need to be scaled up to maximize the available resources for migration and reducing downtime. During optimization phase, post migration, or further scale up compute or storage tiers if the servers are found to be running at maximum capacity and experiencing throttling thereby delivering sub-optimal performance.


Migrate databases to Azure Database for MySQL

You may use MySQL utilities such as mysqldump., PHPAdmin or MySQLDumper to dump and load databases into an Azure MySQL Database in several common scenarios. In other scenarios, you may use the Import and Export approach instead.

  • Use database dumps when you are migrating the entire database. This recommendation holds when moving a large amount of MySQL data, or when you want to minimize service interruption for live sites or applications.
  • Make sure all tables in the database use the InnoDB storage engine when loading data into Azure Database for MySQL. Azure Database for MySQL supports only InnoDB Storage engine, and therefore does not support alternative storage engines. If your tables are configured with other storage engines, convert them into the InnoDB engine format before migration to Azure Database for MySQL.
  • To avoid any compatibility issues, ensure the same version of MySQL is used on the source and destination systems when dumping databases. For example, if your existing MySQL server is version 5.7, then you should migrate to Azure Database for MySQL configured to run version 5.7. The mysql_upgradecommand does not function in an Azure Database for MySQL server, and is not supported. If you need to upgrade across MySQL versions, first dump or export your lower version database into a higher version of MySQL in your own environment. Then run mysql_upgrade, before attempting migration into an Azure Database for MySQL.

Note: In the Azure Database for MySQL service, a gateway is used to redirect the connections to server instances. After the connection is established, the MySQL client displays the version of MySQL set in the gateway, not the actual version running on your MySQL server instance. To determine the version of your MySQL server instance, use the SELECT VERSION(); command at the MySQL prompt.

  • Exports users and permissions following the mysqldump. Direct export of the MySQL system schema is not recommended. Password cannot be migrated since it is stored in encrypted format in mysql.user table. Users and their privileges shall be exported from old database server using the following steps instead.

Run the following bash command to create a .sql file containing SQL statements to recreate all the users.


mysql -B -N -h << {{ old-mysql-server-name }} >> -uadmin -p'password' -e "SELECT CONCAT('CREATE USER \'', user,'\'@\'', host, '\' IDENTIFIED BY \'passw0rd\'') FROM mysql.user WHERE user NOT IN ('debian-sys-maint', 'root', '', 'mysql.*')" mysql > create_all_users.sql


Run the following bash command to create a .sql file containing SQL statements to grant all existing privileges of the user accounts captured above:


while read line; do mysql -B -N -h << {{ old-mysql-server-name }} >> -uadmin -p'password' -e "SHOW GRANTS FOR $line"; done < mysql_all_users.txt > grant_privileges_to_users_sql.sql


Step-by-step guidance to migrate the MySQL database to Azure Database for MySQL is provided here. If you want to perform online migration with minimal downtime, you can follow the step-by-step guidance here.


Change the connection string

After the database is migrated to complete the end to end migration of the WordPress website you would need to change the connection in wp-config.php. Most WordPress blogs prefer to store the hard-coded database information in wp-config.php. In this scenario, you can change the relevant parameters of the database connection string in wp-config.php as shown below


Code in wp-config.php:

/** MySQL database name */

define('DB_NAME', 'database-name');

/** MySQL database username in username@servername format for Azure DB for MySQL */

define('DB_USER', 'database-username@servername');

/** MySQL database password */

define('DB_PASSWORD', 'database-password');

/** MySQL hostname */

define('DB_HOST', 'database-host');


If you are using environment variable to specify database connection string, you can use Application settings as documented here.


Note:  The username format is username@servername. The target Azure Database for MySQL servername is of the format <servername>


Then launch the WordPress website to ensure that it properly connects to newly migrated database hosted on Azure Database for MySQL server without any issues or data loss.


Post-migration verification

After you have successfully migrated your application and respective databases, you need to go through a series of post-migration tasks to ensure that everything is functioning as smoothly and efficiently as possible.

For the databases specifically, after the data is migrated to the target environment, validate the data migration to ensure there are no data consistency issues.

  • The simplest way is comparing the row counts of each imported table. There should be no difference between row count between the tables on source MySQL server and the imported tables in the new Azure Database for MySQL server.
  • Check the physical integrity of tables by CHECKSUM TABLE statements. The statement will return the checksum of a table. Compare the checksum values between the exported tables temporary replica and the imported tables in the new instance:

         CHECKSUM TABLE << table_name >> EXTENDED


Note: Running CHECKSUM TABLE on large table may require extended period of time, and QUICK option is not supported with InnoDB engine which is the default in Azure DB for MySQL.

  • Perform sanity check to ensure all the users and privileges are imported right by running the following command in the new Azure Database for MySQL server,

    SELECT * FROM mysql.user
    WHERE user NOT IN ('debian-sys-maint', 'root', '', 'mysql.*');

    Compare the results, check the list of users and the associate privileges (columns with name end with _priv).



After you complete your post migration verification, it is important to use an iterative optimization process to ensure the best performance and functionality of your solution in the target environment. If the database compute tier was scaled up to expedite migration and minimize downtime, you would scale it down for optimal use of resources. With Azure Database for MySQL, we have Performance Recommendation which analyzes the runtime behavior of the database and offers customized recommendations to improve performance. Further, you may want to explore Reserved Capacity for Azure Database for MySQL to further optimize your cost.


For additional information, refer to the following resources.


Parikshit Savjani
Principal Program Manager, Microsoft

1 Comment
Version history
Last update:
‎Jan 26 2020 10:38 PM
Updated by: