Understanding the Upgrade Status Module: Your Pre-Flight Check Before Any Drupal Upgrade

migration last_updated: 2026-07-09 reading_time: ~4 min

If you've ever started a Drupal major version upgrade only to get blindsided by a pile of deprecated code halfway through, the Upgrade Status module is the tool that's supposed to stop that from happening. It's the closest thing Drupal has to a pre-flight checklist, and every developer doing upgrade work should know how to read its output.

What it actually does

Upgrade Status scans your site's core environment, contributed projects, and custom code, and tells you three things:

  1. Whether your hosting environment meets the requirements of the next major Drupal version (PHP version, database version, Composer version, and so on).
  2. Whether your contributed modules and themes have compatible releases available.
  3. Whether your custom code uses deprecated APIs that will break on the next major version.

That third point is the real value. Under the hood, it uses PHPStan with the mglaman/phpstan-drupal extension, plus specialized checks for Twig templates, CSS selectors, library definitions, and routing files — catching things a generic static analyzer would miss entirely.

Installing it

composer require --dev drupal/core-dev:^11 --update-with-all-dependencies composer require drupal/upgrade_status drush en upgrade_status -y

The core-dev package is important and easy to skip — without it, Upgrade Status will throw false errors because it can't find the PHPStan rule files it depends on for scanning.

Running a scan

In the UI, it lives at Administration > Reports > Upgrade Status. Select the projects you want to check and click Scan selected. For custom code this can take a little while depending on how much there is to analyze.

If you'd rather run it from the command line (and you should, especially for CI):

drush upgrade_status:analyze --all --ignore-uninstalled

There's also a shorthand alias, us-a, and options like --ignore-contrib or --format=codeclimate if you want to wire the results into a GitLab CI pipeline.

Reading the report

The report is organized into a few sections worth understanding:

  • Environment checks — is your PHP version, database, and Composer version ready for the next major?
  • Update section — contributed projects with a newer Drupal.org release available, and whether that release is compatible with the next major version.
  • Scan section — your custom modules and themes, where the deprecation analysis actually happens.
  • Collaborate with maintainers — contributed projects with no compatible update yet, along with links to the relevant issue queues.

Each deprecation finding gets categorized: fix now, fix later, fixable automatically with Rector, or safe to ignore. That triage is genuinely useful when you're deciding where to spend your time first.

What it won't do for you

Upgrade Status finds deprecated code — it doesn't fix it. For that, pair it with drupal-rector, which can automate a large share of the mechanical fixes:

composer require --dev palantirnet/drupal-rector cp vendor/palantirnet/drupal-rector/rector.php . vendor/bin/rector process web/modules/custom --dry-run

Drop --dry-run once you've reviewed the proposed diff and you're happy with it.

A practical workflow

For a real upgrade project, this is roughly the order that works well:

  1. Get your environment (PHP, database, Composer) to spec for the target version first — Upgrade Status will nag you about this until it's done.
  2. Update contributed modules and themes to versions that support the next major, while you're still on the current major.
  3. Scan your custom code, and work through the "fix now" items — running Rector first to knock out the easy wins.
  4. Re-scan. Repeat until the report is clean.
  5. Only then actually flip core over to the next major version.

Doing the contrib and custom code work before the core upgrade, rather than during it, is the single biggest thing that separates a smooth upgrade from a stressful one. Upgrade Status is what makes that sequencing possible, because it tells you exactly what state your codebase is in before you commit to the jump.