A series for people who know they need to upgrade but aren’t sure how to begin.
I’ve been doing this for a while.
My first Drupal site went live in 2007, built on Drupal 6. Since then I’ve shepherded a project through every major version transition: 6 to 7, 7 to 8, 8 to 9, 9 to 10. Each time I did it more or less on my own — reading the change records, working through the deprecation notices, crossing my fingers on deployment day, and eventually landing on the other side with a working site and a few more gray hairs.
So when Drupal 11 came along, my instinct was the same: roll up my sleeves and work through it. But something was different this time. The project I’m upgrading — a multi-site Drupal installation hosting four independent subsites on a shared codebase — had accumulated enough complexity that the upgrade felt genuinely daunting. Multiple subsites sharing a single database. A theme stack built on Bootstrap 3, a major version behind. Module dependencies ranging from rock-solid to “let’s hope someone is still maintaining this.”
This time, instead of diving in alone, I decided to do something I hadn’t done before: ask for help developing a plan.
Specifically, I used Claude Code to help me think through the upgrade systematically — not to write the code for me, but to help me break an overwhelming task into a concrete, ordered checklist of steps that each felt manageable on their own. The result was a phased upgrade plan that turned “upgrade to Drupal 11” from a looming wall into a series of doors I could open one at a time.
This series of posts documents what we came up with and how it actually played out. If you’re sitting in front of a Drupal 10 site wondering where to even begin, I hope it’s useful.
The Core Insight: Sequence Matters
The single most useful thing that came out of planning the upgrade was understanding that the order of operations matters enormously. You can’t just run composer update and hope for the best. Certain things need to happen before other things, and skipping steps — or doing them out of order — creates problems that are hard to untangle.
The plan we developed breaks the work into eight phases:
- Assess — run Upgrade Status, understand what’s broken before touching anything
- Infrastructure — get PHP and the database engine to versions Drupal 11 requires
- Module and theme compatibility — resolve everything that won’t work on D11 before upgrading core
- Backups — take snapshots before making the irreversible changes
- Upgrade core and contrib — the actual version bump
- Database updates — run
updbon each subsite - Testing — verify everything works
- Deploy — push to production
The key principle: phases 1 through 3 are all about reducing risk before you change the Drupal version at all. By the time you actually run composer require drupal/core:^11, you want to have already resolved every known blocker. If you do it the other way around — upgrade first, fix problems after — you end up debugging multiple things at once with a broken site.
Why Planning First Changes Everything
If you’ve done Drupal upgrades before, you might be tempted to just look at the Upgrade Status report and start fixing things as you find them. That works for simple sites. For anything with real complexity, it tends to lead to a long afternoon of whack-a-mole.
The planning approach forces you to see the full landscape before committing to any changes. In my case, that revealed a few things I hadn’t fully reckoned with:
- The database server (MariaDB on Platform.sh) needed a major version upgrade, and Platform.sh doesn’t automatically migrate data across major versions — meaning I needed to dump and re-import the database manually as part of the infrastructure work.
- The Bootstrap 3 theme — which four of my custom subthemes depended on — has no Drupal 11 support and never will. The theme migration wasn’t optional; it was a prerequisite for the entire upgrade.
- Some modules I was running were on alpha or RC releases, and I needed to check whether stable D11-compatible versions existed before I could update constraints in
composer.json.
None of these were surprises exactly, but seeing them laid out as a prioritized list made it clear what needed to happen in what order, and which problems were actually blockers versus things I could handle along the way.
What’s Coming in This Series
This is the first in a series of five posts. Here’s what we’ll cover:
- Post 2: Phase 1 (Assessment) and Phase 2 (Infrastructure) — running Upgrade Status, understanding the results, and getting the database engine upgraded
- Post 3: The beginning of Phase 3 — the module and theme compatibility work, and the decision to migrate away from the Bootstrap 3 theme
- Post 4: The Bootstrap 3 to 5 migration in detail — what actually changed in the templates, CSS, and block placements
- Post 5: Phase 4 through 8 — backups, the core upgrade itself, database updates, testing, and deployment
Each post follows the same structure: a narrative section describing what we did and why, followed by an Expert Mode section with the actual commands.
Let’s get into it.
Expert Mode: Setting Up for the Upgrade
Before doing anything else, make sure you have a working local development environment and can run Drush against each of your subsites. For this project, that means DDEV.
Verify your environment:
# Check your PHP version — D11 requires 8.3+ ddev php --version # Verify Drush can reach each subsite ddev drush --uri=aircooled status ddev drush --uri=careersinspanish status ddev drush --uri=figueroa status ddev drush --uri=svloba status
Install the Upgrade Status module:
ddev composer require drupal/upgrade_status --dev # Enable on each subsite for site in aircooled careersinspanish figueroa svloba; do ddev drush --uri=$site en upgrade_status -y done
Visit the report on each subsite:
https://aircooled.ddev.site/admin/reports/upgrade-status https://careersinspanish.ddev.site/admin/reports/upgrade-status https://figueroa.ddev.site/admin/reports/upgrade-status https://svloba.ddev.site/admin/reports/upgrade-status
Check which theme each subsite is using:
for site in aircooled careersinspanish figueroa svloba; do echo "=== $site ===" ddev drush --uri=$site config:get system.theme done
Don’t fix anything yet. The goal of this step is to build a complete picture of what you’re dealing with. Write it down, make a list, and then we’ll start working through it in order.
Read the next post - Get a Sanity Check with Upgrade Status.