Before: the assessment nobody skips twice

The single biggest upgrade risk is the code you do not know about. Before anything else, establish a complete inventory: every contrib module and version, every custom module and what it does, the theme and its overrides, the database schema for custom entities and fields, and the server configuration.

Then run a static audit of custom code against the target version. Drupal releases deprecation notices for a reason: each one is a map of what will break. Address deprecations and outdated API usage in a dedicated pass before the major version change.

Finally, decide the module strategy: which contrib modules have an official release for the target version, which have a recommended alternative, and which custom modules should be replaced outright because maintaining them is no longer worth it.

# Deprecation scan on custom code before upgrading
composer require --dev mglaman/phpstan-drupal
vendor/bin/phpstan analyse web/modules/custom --level 5

During: staging, upgrades and the discipline of small steps

Create a staging environment that is as close to production as possible — same infrastructure approach, a recent database copy (scrubbed of personal data), and the real codebase. Never upgrade against a production database blind.

Run the upgrade path in this order: core first, then contrib modules, then themes, then custom code. After each stage, run configuration export and a smoke test. Keep a documented step-by-step so the process can be repeated — your future self will thank you during the next upgrade.

Do not use the one-click upgrade UI for anything but small sites with zero custom code. On real projects, a scripted upgrade in a Git branch, reviewed and tested, is the only sane approach.

After: the work that makes the upgrade stick

The launch is not the finish line. Plan the stabilization window: watch error logs, monitor Cron, verify every critical flow end-to-end, and keep a rollback path warm for at least a week.

Update the project documentation: the module inventory, custom code notes and deployment runbook. A Drupal upgrade is also a knowledge transfer — the site should be easier to maintain after it, not just newer.

And schedule the next review. A supported version with an active maintenance plan is the difference between an upgrade and a rescue later.