Series Overview & ToC | Previous Article | Next Article

Now that we have covered how to prepare for a migration, let’s put that knowledge into practice. In this article we introduce the example project: a Drupal 7 site that we will be migrating to Drupal 10. After providing an overview of project setup, we will perform an audit of the Drupal 7 site and draft a migration plan to Drupal 10.

Example repository

The repository is available on Github. We will be using DDEV to set up local development environments for Drupal 7 and 10. Refer to DDEV’s official documentation for installation instructions. If you choose to use a different development environment, adjust the commands accordingly.

To get the Drupal 7 site up and running, execute the following commands:

git clone d7_to_d10_migration

cd d7_to_d10_migration/drupal7

ddev start

ddev import-db -f ../assets/drupal7_db.sql.gz

ddev import-files --source ../assets/drupal7_files.tar.gz

ddev restart

ddev launch

ddev drush uli

This will clone the repository into a folder named d7_to_d10_migration. Inside, you will find a drupal7 folder with the code for a Drupal 7 installation including contrib modules. The commands also import an already populated database and user uploaded files from the assets folder.

The last command we used above (ddev drush uli) will give you a link to log in as an administrator. The Drupal 7 site will be available on your local machine at

We are going to provide instructions for setting up the Drupal 10 site in the next article. For now, let’s focus on understanding the source of our migration.

Our example project is a website that shares information about Drupal meetups. It collects information about speakers and the sessions they present, venues where on-site events happen, and organizations that sponsor the meetups. To have a deeper understanding of the site, we are going to perform an audit following the template introduced in article 3 - Migrating Your Data from Drupal 7 to Drupal 10: Source Site Audit - An In depth Analysis.

Drupal 7 modules and themes analysis

The first tab in the template lists modules and themes. While it is possible to fill out the template manually, the example repository contains a file with commands that would help with the task. Execute the following command to get a list of projects with their version and status:

ddev drush pm:list --fields=package,project,name,type,status,version --format=csv | sort > d7_projects.csv

This will generate a file named d7_projects.csv Open it with any spreadsheet software or copy the data into the Google Sheet template itself.

In either case, what we want is the ability to filter the different columns to make analyzing the data easier. For example, you can filter for enabled projects only to determine what action to take for each in Drupal 10. Conversely, you can show a list of disabled (and not installed) projects to inquire why they exist in the code base if not in use.

Refer to article 3 - Migrating Your Data from Drupal 7 to Drupal 10: Source Site Audit - An In depth Analysis for an explanation of the template. For reference, some actions to take based on the Drupal 7 site are:

Drupal 7 content model audit

Let’s proceed with an analysis of the content model. To make this process easier, we need access to the Drupal 7 database to issue SQL queries. When using DDEV, there are a few options:

  • Use ddev mysql to access SQL prompt where you can perform the queries directly.
  • Install a DDEV add-on to make a database GUI available. A common one is phpMyAdmin, a web-based SQL client, which can be launched using ddev phpmyadmin when installed.
  • Use ddev describe to get connection information for the database managed by DDEV. You can use this information to connect to the database from a desktop application installed in your host machine. Also, some IDEs like PhpStorm contain database browsers which you could also leverage.

Independently of which way you prefer to run the SQL queries, refer to the D7 site audit document for examples that can be used to populate the template. The query below will get information regarding content types for the second tab in template:


	nt.module AS provider_module,

	nt.type AS machine_name,,


	COUNT(n.nid) AS node_count,

	COUNT(CASE WHEN n.status = 0 THEN 1 ELSE NULL END) AS unpublished_count

FROM node_type AS nt

LEFT JOIN node AS n ON n.type = nt.type

GROUP BY nt.type

ORDER BY node_count DESC;

This query will produce a list of all content types. For each of them, the total number of nodes and the count of unpublished nodes will be displayed. The template includes a formula to get a percentage of unpublished nodes. The query result also includes the module that provides the content type. In the example project, it is the node module for all of them because the content types were created using Drupal’s admin interface. Some Drupal 7 modules like user alert create a new content type to fulfill its functionality. In such cases, the machine name of the module that provides the content type will be listed.

Our example site does not include a lot of content. The number of nodes per content type is rather low, but even with the sample data we can identify some patterns that would affect the migration. Namely, all nodes of type swag are unpublished. Therefore, there is no need to carry this content type into the new Drupal 10 site. This was done intentionally to demonstrate how we can skip full content types from the migration.

A content type with a high percentage of unpublished nodes or a low number of total nodes should be reviewed to determine whether it is worth keeping. Refer to article 2 - Migrating Your Data from Drupal 7 to Drupal 10: Source Site Audit - A High Level Overview for more things to consider when deciding which content type to migrate.

For brevity, we will not list nor explain all the queries in the document. Give them a try and populate a copy of the template with data from your project.

Migration plan for Drupal 10

Now that you have completed the audit of the example source site, let’s draft a migration plan for Drupal 10.

Based on information collected in the site audit document, we will:

  • Migrate nodes of type speaker as user entities.
  • Migrate nodes of type sponsor as taxonomy term entities.
  • Not migrate nodes of type swag and drop the content type altogether.
  • Not migrate any unpublished node.
  • Not migrate any blocked users.
  • Not migrate revisions for any content entity.
  • Migrate the field_favorite_quote field collection into paragraph entities.
  • Migrate field_video_recording of type youtube into media entities of type remote video.
  • Migrate field_slides of type file into media entities of type document.
  • Migrate field_profile_picture of type image into media entities of type image.
  • Merge the field_drupal_org_profile, field_linkedin_profile, and field_x_twitter_profile URL fields into a single field using the social link field module.
  • Migrate the field_website URL field into a link field.
  • Migrate field_address of type addressfield into Drupal 10’s address module.

Some of the content model changes are arguably not necessary in our rather simple example project. Yet, we will go forward with them to have a broad array of examples. This will allow us to demonstrate different techniques that you will be able to reference (and adapt) on your own projects.

Before closing, a list of bullet points like the one presented above is far from being a useful migration plan. A proper one goes beyond configuration and content considerations, which are the focus of this migration series. Among other things, a proper plan should include:

  1. An analysis of contributed modules and theme usage. When dropping or replacing anything, explain the rationale behind the decision.
  2. An assessment of custom functionality and a plan to port custom modules and themes as necessary.
  3. A list of existing third-party integrations and how they will be handled on the new site.
  4. A review of the current server infrastructure and potential changes due to higher version requirements in Drupal 10.
  5. Risk management, resource allocation, launch deadlines, and other business considerations.

For more information, we recommend watching this presentation on planning and estimating Drupal migrations presented by the Tag1 team at DrupalCon Portland 2024.

We covered a lot of territory quickly today. Take some time to explore the provided Drupal 7 site and practice running the queries in the document. Compare your migration plan with our example above. These are foundational planning steps that will be important when you begin your own migration. In our next article, we will provide instructions for setting up the Drupal 10 site.

Quick Resources