Third & GroveThird & Grove
Feb 24, 2021 - Jeremy Dickens

Drupal 9 Upgrade Considerations

eye glasses

The advent of Drupal 8 brought about many new features and improvements. One highly anticipated change was the move to a new structured release cycle. The update promised to improve compatibilities between versions, introduce gradual deprecation of old APIs alongside new features, and strongly suggested that the days of performing full-site rebuilds to move between major versions of Drupal were in the past.

Now that Drupal 9 has been released, we’ve had the opportunity to work through the upgrade process from Drupal 8 and found that it is indeed a significantly lower lift than doing re-implementations while moving to Drupal 8. That being said, there are still important considerations to keep in mind when preparing and executing your upgrade to Drupal 9.

Required Tooling
The first step of any project is making sure you have the proper tools to proceed, and Drupal upgrades are no different. Because the first challenge is finding and fixing all of the deprecated code and identifying modules that need updating, you will need a tool to help you. Fortunately, the Upgrade Status module gives you almost everything you need by checking:  

  • Global requirements to ensure our environment is configured correctly and has all of the prerequisites installed to run Drupal 9. 
  • Contributed modules to see if they are Drupal 9 ready, have a compatible upgrade, or have a patch available to make them compatible.
  • Custom code to identify deprecations and required changes.
  • Themes for deprecated Twig syntax.
  • Any installed libraries for deprecation status, required changes to our info.yml files, and other possible compatibility issues.

Upgrade Status can be run with Drush or from within your Drupal site, but it’s not a good idea to run this on production. Instead, install it as a dev requirement and run it locally or on your development or local environment. If your codebase is larger, the checks can take a little bit of time to run, particularly when run locally. You can run against a subset of your site’s modules if necessary and export the results after running the checks.

If your site has a significant amount of custom code, you also want to install Upgrade Rector. This module uses the Rector PHP refactoring library to automatically generate patches to fix the deprecations in your code. While it can’t fix everything, it can significantly speed up the process.

Updating Core
Routine site maintenance should always include installing and testing updates to the latest versions of Drupal Core and installed contributed modules. While Third And Grove’s support process consists of this as part of our regular support contracts, it’s a fact of life that many teams struggle with prioritizing these updates over more critical work to meet actual business goals. If your site is well-maintained, this step will be easy: The Upgrade Check report will be mainly Green, and you are well on your way to being ready for D9.

More commonly, sites will lag on updates, and your reports will show several updates that need to be applied. The first step of the Drupal 9 preparedness project should be to ensure that you are running the latest version of Drupal 8 (8.9.13 at the time of this writing).  Drupal 8.9 is the long-term support version of Drupal 8 and is the ideal starting place for a D9 upgrade. If your site’s code is working on Drupal 8.9 and clean of any deprecations, it should work with Drupal 9 since they share the same public APIs.

The first major stumbling block many upgrades hit is when the site has lagged significantly behind the Drupal update schedule and is currently on a version of Drupal older than 8.8.  This can be problematic because each Drupal feature release introduces different overall requirements and various changes under the hood that can require database updates and other special handling. To address this, we strongly recommend first reviewing the release notes of each minor version (i.e., Drupal 8.4.0, 8.5.0, etc.) and note the changes introduced by each version. Changes include the fact that Drupal now requires PHP 7.3 or greater, the addition of new core modules (such as Workflows, Media Library, and JSON: API), changes to the way path aliases are handled, and the introduction of a new set of Composer packages and a default project template. Make a note of each change that may impact your particular site install and correct any discrepancies that may arise.

Once reviewed, we don’t recommend jumping directly to 8.9 unless you are on a version *prior* to 8.6.1. Generally, you want to perform each minor upgrade individually and test them before moving on to the next version. Still, if there was a bug related to taxonomy updates in the update to 8.6, that is best avoided. Otherwise, use Composer to require and install the latest patch release of a specific version, run any database updates, and test your installation running that version before moving on to the next minor version upgrade.

Update Contributed Modules
By this point, you have used Upgrade Status to generate a list of modules your site uses and their readiness for Drupal 9. This is a straightforward process for most common modules: The module will have a version ready that is compatible with both Drupal 8 and 9, and you will update it as usual (after reviewing the release notes — see the next section). There are three cases where this can become less straightforward:
No Update Available, But There Is A Patch
Some module maintainers may not have released a version of the module with the required Drupal 9 changes yet, but Upgrade Status tells you that a patch is available for the module. One tricky aspect of this is that if some of the required changes are to the module’s composer.json file, they cannot be patched using Composer. This is due to the way it checks dependencies — a classic chicken and egg problem. While in general, it is not recommended to add contributed modules to your codebase, you can pull the modules that require patching into your project, remove them as composer dependencies, and then follow the [process of applying that patch to your codebase with Composer](  If you have to take this approach, you should continue monitoring the project and adding it back to your composer.json when the module is D9-ready.

Module Has No Patches Available
Because of the Drupal 9 Project Readiness Bot, most modules should have at least one patch available to bring the module up to speed from a compatibility standpoint. However, if you are using a module that does not, there’s still hope. With the information that Upgrade Status gives you about specific deprecations and the patches generated by Upgrade Rector, you can patch the module yourself, making it ready for other users.  

When you build these patches, we recommend following the standard Drupal module contribution guidelines and working on the module against the dev version outside your site’s codebase. Once the patch is built, you can contribute it back to the community via the project’s issue queue, then follow the process outlined above for a module that has a patch available.

Update Is A Major Version Change
We have seen one tricky situation arise with some contrib modules: modules that have a version that supports Drupal 9, but the version is also a major release with breaking API changes. This is rare but worth noting, especially if the module is one that your custom code depends on in some way. Big API changes in a module behind the scenes may significantly impact your site and require that you refactor your code to account for them. 

Updating Custom Code
Your custom code can be the most significant source of potential changes to your codebase in preparing your site for Drupal 9, especially for long-running projects that started in the early days of Drupal 8. The API changes and deprecations in D9 are well-known and documented. Still, it’s never surprising to find that routine maintenance has taken a back seat to implement new functionality to handle new business requirements.  

Fortunately, the tools for upgrading Drupal also handle custom code, pointing out where the deprecations are, what changes need to be made, and sometimes even making the change itself using Upgrade Rector. Rector can’t fix every deprecation, but it can automatically make quick work of many of the items, freeing up developer time to tackle more difficult changes. This is also an opportunity for possible efficiency, as many custom module updates could be happening in parallel to the contributed module work.

Testing Your Upgrade
Once the code is all in place and all database updates have been run, it’s time to test your site for potential regressions. Most issues and edge cases can be caught when performing the upgrades themselves, which is one reason we suggest performing the module upgrade steps one-at-a-time. If you update one module at a time (or in small groups of modules of similar/shared functionality), obvious regressions and unexpected behavior can be caught early, reviewed, and fixed. If you have enough hands, fixing problematic code can be handled by one developer while another developer continues updating and testing other modules.

A smart strategy for getting ahead of these issues is to review the release notes for the modules you are updating before beginning the process. Most module maintainers will give guidance on any additional upgrade steps or considerations you should take before upgrading, saving you time and headaches later on in the process.

Once your upgrades are complete, you will want to perform a series of checks of your site's overall functionality to ensure you aren’t running into edge cases that your unique combination of code is surfacing. It’s crucial to check all editorial and administrative functions as well — the site may appear to be operating normally. Still, some unseen interaction could be wreaking havoc with your editors’ ability to update content.  Behavioral and visual regression testing can help accelerate this process. Still, sites with complex interactions and administrative needs should be tested in concert with the actual people who use these sites daily — they are often the people best equipped to detect if something is amiss.

In The End
As we said at the outset, the underlying architecture changes to Drupal 8 brought with them a promise for easier future updates and the ability for our sites to continue to grow and evolve through many major versions of Drupal. Every functioning Drupal site relies on modules from the wider Drupal community for essential functionality. This adds another layer of complexity and dependency on the maintainers of those modules. The community as a whole has been good about maintaining modules to the D9 standard, but it’s not unusual for a site to depend on a module that lags.  

Another critical factor in the upgrade conversation is whether your site has been maintained and kept up to date already. Many site owners struggle to keep their sites' code current, but sacrificing these regular updates makes sites vulnerable to security issues and makes the Drupal 9 upgrade process significantly more difficult. That being said, a well-maintained Drupal 8 site can deliver on the promise of easy upgrades to Drupal 9 and beyond.