Why a Drupal upgrade across two major versions needs a planned stop in between
Drupal major versions cannot be skipped, so a site several versions behind has to be moved as a chain of upgrades, one major version at a time. A Drupal 9 site must move to Drupal 10, then to Drupal 11. A Drupal 10 site must stop on Drupal 11 before it can reach Drupal 12. The intermediate version is not a detour you can drop from the plan; it is the route the core upgrade path requires, and each stop needs its own code changes, contributed module versions and testing.
The deadline is set by end of life. According to the Drupal core release schedule, Drupal 10 reaches end of life on December 9, 2026, and Drupal 12 is scheduled for the week of December 7, 2026. A Drupal 9 site already has no path that avoids several stops, so the first question is whether the site can reach Drupal 11 before Drupal 10 ends. Confirm the current support dates on the schedule page before you fix a plan, since the dates are the basis for every later milestone.
The release cadence explains why the stop matters. The schedule says new major versions typically arrive about every three years, bugfix releases come out on the first Wednesday of each month, and security releases on the third Wednesday. A site that waits on Drupal 10 for a long period will be patched on a monthly and security cycle while the next major version approaches. Plan the Drupal 11 stop as a dated milestone with a named owner, and keep the intermediate site on current security releases until it moves on.
What changes at each major version and what it asks of the team
This table compares what Drupal 10, 11 and 12 each ask of your servers, your code and your contributed modules. Read each row as a gate you must clear before the next step, and treat the module row as the one most likely to stall a project.
| Area | What changes | What it asks of the team |
|---|---|---|
| PHP runtime | Drupal 10 requires PHP 8.1 or later. Drupal 11 requires PHP 8.3 or later. Drupal 12 requires PHP 8.5 or later. | Plan server PHP upgrades as a separate step, and confirm the PHP version each hosting target supports before you start the code work. |
| Database and web server | Drupal runs on Apache, Nginx and other web servers, with MariaDB, MySQL, PostgreSQL or SQLite as the database. | Check that your current database version meets the minimum for the target release, and confirm the exact minimums in the system requirements page. |
| Deprecated API use | Code that compiles on the current version can use APIs that the next major version removes or changes. | Run Upgrade Status on each step, fix flagged custom code, and confirm each removed API against the release notes for that version. |
| Contributed modules | Each contributed module must declare support for the target core version. Some are only compatible with a range of minor versions. | Confirm a compatible release for every module before the step. For example, samlauth 8.x-3.14 supports Drupal 10.3 and later and Drupal 11. |
| Core modules and themes | Some modules and themes have left core in later releases. | Check the removed-from-core list for each step and plan replacements or contributed versions before the code upgrade begins. |
| Intermediate stop | A Drupal 9 site must stop on Drupal 10 before it reaches Drupal 11. A Drupal 10 site must stop on Drupal 11 before Drupal 12. | Schedule each stop as a full release with testing, deployment and rollback, and do not treat the stops as shortcuts. |
| Release timing | Bugfix releases ship on the first Wednesday of each month and security releases on the third Wednesday. Drupal 10 reaches end of life on December 9, 2026. | Confirm the release cadence in the core release schedule and build a patch routine that keeps the site on a supported version during the project. |
What to prepare before the first upgrade step
Most failed Drupal upgrades stall on preparation gaps, not on code. These six items set the baseline for a two-step move, so each intermediate version starts from a known, restorable and tested state.
Full backup of database and files
Take a complete copy of the database and the file system, including private files and the Composer-managed code tree, before touching either version. Test the restore on a separate host, because a backup that has never been restored is an assumption. Keep a dated copy for each intermediate step so you can roll back to the exact version you left, not just to the start of the project.
Inventory of custom and contributed code
List every custom module, custom theme and contributed project with its installed version, its maintainer status and whether a release exists for each target version. Run Upgrade Status against the site to record deprecated API use per project. Projects without a compatible release for the intermediate version usually decide the sequence, so mark them first.
Production-like test environment
Build a staging copy with the same PHP version, database engine, web server, cache layer and sanitized production data. Run each upgrade step there first and capture the time each step takes, since that figure drives the production window. Confirm that cron, queues and any integrations behave the same way in staging, or the test results will not transfer.
PHP and database check per target
Confirm the PHP and database versions required by each target release before you start, because a code upgrade can be blocked by a server that is one version behind. The Drupal PHP requirements page lists the minimum PHP version per major release, so check the intermediate target and the final target separately. Plan server changes as their own tested step.
Freeze on content and configuration
Agree a change freeze with content editors, site builders and anyone who deploys configuration for the full upgrade window. Changes made in production during a multi-step upgrade can be lost on restore or conflict with exported configuration. Record the freeze start and end, and name the person who can approve an exception.
Named owners and a rollback decision point
Assign one owner for each step, one for the contributed module decisions and one person who can call a rollback. Write down the criteria for stopping at each intermediate version, such as failed updates, unresolved fatal errors or missing module releases. Agree these before the work starts so the decision is not made under pressure during the window.
How to sequence the Drupal 9 to Drupal 10 to Drupal 11 upgrade
The sequence moves a Drupal 9 site through a supported 9.x release, a Drupal 10 stop and a Drupal 11 target, with a passing check and a restorable rollback point before each move. Each stop gives the team a known-good state to fall back to if a later step fails.
Confirm the starting point and freeze scope
Record the exact Drupal 9 minor version, PHP version, database engine and every contributed module and theme version in use. Your team or a partner agrees the target dates with the release calendar in mind, since bugfix releases land on the first Wednesday of each month and security releases on the third Wednesday, and avoids scheduling production changes on those days where possible. Freeze content-model and feature changes for the duration of the upgrade. Done when the inventory is signed off and a full backup of code, database and files has been restored successfully to a separate environment.
Bring the site to the latest 9.x release
Update Drupal 9 to the latest supported 9.x release first, because the upgrade path is staged through the 9.x line before a Drupal 10 move. Apply the matching contributed module updates and confirm the site still passes its existing functional tests and smoke tests on staging. Take a snapshot of the production database and code before the production change so you can restore to the pre-update state. Done when staging runs cleanly on the 9.x release, the test suite passes, and the rollback snapshot is verified as restorable.
Prepare the Drupal 10 stop with PHP 8.1
Check that the hosting stack meets the PHP 8.1 minimum that Drupal 10 requires, and that the database and web server are on versions the Drupal system requirements list as supported. Run Upgrade Status against the codebase to list deprecated API use in custom code and contributed projects, and confirm each contributed module has a Drupal 10 compatible release. Plan the server change and the code change as separate, reversible steps. Done when the staging environment runs PHP 8.1 with Drupal 10 dependencies resolved and Upgrade Status reports no blocking items.
Upgrade to Drupal 10 on staging
Upgrade core and contributed projects to their Drupal 10 releases through Composer, keeping the lock file under version control so the build can be reproduced. Fix custom module and theme code flagged by the readiness check, and rebuild any theme component that depends on removed core behavior. Run the automated test suite, check content editing, forms, user login and cron. Done when the Drupal 10 staging build passes tests, the content editing workflow has been exercised by editors, and the deployment has been rehearsed end to end.
Cut over to Drupal 10 and stabilize
Schedule the production change in a window that avoids the Wednesday security and bugfix release days where possible, then take a fresh backup and snapshot immediately before the cutover. After go-live, monitor error logs, cron, queues and integrations, and apply any follow-up fixes as tracked changes. Keep the Drupal 10 build stable for a defined soak period agreed with the business owner before starting the next major step. Done when production has run on Drupal 10 through the soak period with no open severity-one defects and the pre-cutover backup has been retained until sign-off.
Prepare the Drupal 11 target with PHP 8.3
Upgrade the PHP runtime to 8.3, which Drupal 11 requires, on staging first, and confirm database and web server versions still meet the requirements. Re-run Upgrade Status against the Drupal 10 codebase to catch deprecations that only surface for the Drupal 11 target, and check that contributed modules, including samlauth or OpenID Connect where used, have Drupal 11 compatible releases. Done when the staging stack runs PHP 8.3 on Drupal 10 with no blocking readiness findings and the Drupal 11 dependency set has been resolved.
Upgrade to Drupal 11 and close out
Upgrade core and contributed projects to Drupal 11 on staging, repeat the full test and editorial checks, and rehearse the production change. Schedule the cutover with a fresh backup and snapshot taken immediately before the change, and keep the Drupal 10 snapshot available until the Drupal 11 site has run stably. After sign-off, record the final versions, the rollback points used and the test evidence in the change log. Done when production runs Drupal 11 on PHP 8.3, the change record is complete, and the team has confirmed the rollback path is no longer needed.
Keeping the time on each version short
The time your site spends on the intermediate version is a direct driver of total risk. On a Drupal 9 to Drupal 11 project, Drupal 10 is a stop, not a destination, so every week the site runs on it is a week of exposure to a version that is already nearing end of life. Plan the Drupal 10 stop as a short, dated branch with a named cutover, and agree the target date for leaving it before the first upgrade ticket is closed. Check the Drupal core release schedule for the current end-of-life date of the version you are passing through, since that date sets the outer limit of your plan.
Most of the work that makes the second hop short is done while the site is still on Drupal 9. Run Upgrade Status against the Drupal 9 codebase and fix every deprecation it reports in custom modules and themes before the core update begins, so the Drupal 10 stop carries only the changes that version forces. Move custom code to the APIs of the next version in the same branch rather than maintaining two parallel codebases, and keep contributed modules on the newest release that supports each step. Drupal Rector can clear much of the mechanical change, but the remaining manual fixes should be tracked as named tickets with owners.
Drupal 6 and 7 sites follow a different path and should be assessed separately. Drupal.org documentation states that these sites cannot simply be updated to Drupal 10 or later; they are migrated into a new site using the core Migrate, Migrate Drupal and Migrate Drupal UI modules or Drush, and themes must be rebuilt. Drupal 7 security support ended on January 5, 2025, so confirm early whether a Drupal 7 site is still in service and whether it depends on an extended support provider listed by the Drupal Association while migration is scheduled. Treat that decision as a separate project with its own scope and budget.
How to test and roll back each hop
Every hop gets its own functional test pass on the version it lands on, run against a copy of production content rather than a clean fixture set. Intermediate versions are easy to skip in testing because the team is focused on the final target, yet a Drupal 10 stop can expose a broken custom module, a theme incompatibility or a changed admin workflow that would otherwise surface only after the final upgrade. Testers should cover content types, paragraphs or layouts, editorial workflows, user roles and permissions, forms, cron-driven tasks and the admin screens editors use daily. Treat the sign-off as a written record tied to the exact code and database snapshot that were tested.
- Replay real content: Use a sanitized production database so that edge cases in old content, such as unusual field values or legacy text formats, are exercised.
- Cover custom code: Test every custom module and theme on the version under test, including hooks, plugins and Twig templates that were changed during the hop.
- Check editorial flows: Confirm that create, edit, revision, publish and unpublish actions behave as the content team expects.
- Record a sign-off per hop: Note the Drupal and PHP versions, the Composer lock file and the snapshot identifier for each pass.
- Verify scheduled work: Confirm cron, queues and any Drush commands run to completion on the new version.
Before approving a hop, check that the sign-off record names the exact artifacts that were tested so the next hop can be traced back to them.
Performance and integration testing matters at each hop because the surrounding systems often change behavior with the Drupal version: PHP runtime, caching defaults, session handling and contributed modules that connect to outside services. Identity, CRM and search integrations are the most common sources of late surprises, since they depend on libraries and configuration that were written against a specific core release. Load tests should use a realistic traffic profile for your site, and the integration checks should run against test instances of each external system rather than against production. Where a contributed module is the integration point, confirm its release supports the Drupal version in use before testing begins.
- Single sign-on: For SAML or OpenID Connect, confirm login, logout, attribute mapping and account creation on first sign-in. The samlauth module's project page lists support for Drupal 10.3 and later and Drupal 11, so check the version pairing at each hop.
- CRM and API connections: Confirm that field mappings, queue workers and retry behavior still work after the hop.
- Search indexing: Rebuild the index on the target version and compare result sets with the previous version for a fixed set of queries.
- Caching and page speed: Measure cache hit rates, page render times and database query counts before and after each hop.
- Background jobs: Confirm that queues, scheduled imports and webhooks process their backlog within expected windows.
Before approving performance results, confirm that the test environment matches production in PHP version, database engine and cache configuration.
Every hop needs a restorable point before the upgrade starts, and a documented rule for when to roll back instead of fixing forward. A restore point usually combines a database dump, a copy of the file system including the public files directory, and the exact Composer lock file, so the code and data can be returned to a consistent state together. Rollback is most reliable before content editors write new data on the target version, because once editors create nodes, users or revisions on the new schema, reverting the database can discard their work. Decide the rollback threshold with the content owners before the hop, not during the outage.
- Snapshot before cutover: Take a full database backup and a files backup immediately before the production switch, and verify that it restores in a separate environment.
- Freeze content writes: Where possible, schedule the hop during a window when editors are not publishing, or place the site in read-only mode for the cutover.
- Agree a rollback threshold: Define in writing which failures trigger rollback, such as broken login, data loss in a core content type or failed scheduled imports.
- Keep the previous version runnable: Retain the prior code release and its PHP runtime until the next hop has passed sign-off.
- Plan for data written after cutover: If editors have created content on the target version, decide whether to fix forward or to export and re-import that content after a rollback.
Before each hop, confirm who has authority to call a rollback, how long a restore takes in your environment, and who signs off on the next hop.
What makes a two-version Drupal upgrade take longer
This table compares the factors that raise or lower effort when a Drupal site crosses two major versions in one project, such as Drupal 9 to Drupal 11. Read each row as a question to answer about your own estate before asking for a quote, because the effect multiplies when several drivers are high at once. The main takeaway is that the intermediate version doubles the work on each shared driver, so the cheapest reductions come from cleaning up custom code and contributed dependencies early.
| Driver | Effect on effort | How to keep it down |
|---|---|---|
| Custom modules and themes | Each custom module and theme is changed twice, once for each major version, so effort grows with the amount of custom code. | Remove unused custom code and run Drupal Rector and Upgrade Status on each codebase before the project starts. |
| Contributed modules without a release for the next version | A module with no release for the next major version can block the whole chain, forcing a replacement, a fork or a wait. | Check each contributed project's compatibility with the intermediate version first, and decide on replacements early. |
| Custom integrations (identity providers, CRMs, search) | Integrations often depend on contributed or custom code that changes between versions, so each one needs regression testing twice. | List every integration with its owner and test cases, and confirm vendor support for the target library versions. |
| Database size and content volume | Larger databases lengthen each upgrade run, backup and rollback test, and content checks after each step. | Archive or prune stale content before the upgrade and time the update scripts on a full-size copy. |
| Multisite count | Each site in a multisite estate repeats the upgrade steps, and shared code changes affect all sites at once. | Group sites by shared codebase and upgrade a pilot site first, then roll out in batches. |
| Hosting changes | Moving to a new PHP version, database or web server adds infrastructure work that must match each code step. | Confirm the PHP and database requirements for each intermediate version and agree the server upgrade order with the code plan. |
| Environments kept in step | Development, test, staging and production must be upgraded in the same order, and drift between them adds rework. | Use one version-controlled build and release process for every environment and record each step in a shared runbook. |
Questions teams ask before upgrading Drupal across two versions
How much does upgrading Drupal across two major versions cost?
No fixed figure applies to every site, because the cost follows the work in your own codebase. Drupal itself is free under GPL-2.0-or-later, so you pay for people and infrastructure, not licenses. The main cost drivers are the amount of custom code in modules and themes, the number of contributed modules that need a compatible release on each step, the depth of deprecated API use, and how many environments must be rebuilt and tested. Each intermediate version is a separate piece of work with its own testing. DeployOpen works to a fixed-scope written quote agreed before work starts, so ask any partner, including us, to itemize the readiness audit, each version step, testing, and cutover. Ask whether the quote covers one step or the full path.
How long does a two-version Drupal upgrade take?
Duration depends on the scope you agree, not on a standard number of weeks. The schedule is set by the size of custom code, contributed module readiness, hosting changes such as PHP and database versions, the availability of your content owners for testing, and your change control windows. Each major step needs its own build, test and sign-off, so two steps take roughly twice the testing of one. Drupal's core release schedule also matters: bugfix releases arrive on the first Wednesday of each month and security releases on the third Wednesday, and your team needs to absorb those during the project. Ask for a timeline that shows each step, the gates between them, and the dates your own staff must commit.
What does our internal team need to provide for the upgrade?
The project depends on decisions and access that only your organization can give. Plan for four groups:
- Access to the codebase, Git repository, hosting accounts, and non-production environments with a recent copy of the database and files.
- A named decision maker who can approve scope changes, retire features, and accept or defer contributed modules that lack a compatible release.
- Content owners who can review pages, forms, and workflows on each intermediate version, because functional sign-off is not a developer task.
- Operations staff who own DNS, certificates, backups, and the production change window.
Agree these responsibilities in the written scope so delays from missing access are visible and do not get charged as surprises.
Can our own team upgrade Drupal across two versions without a partner?
Yes, if your team has Drupal developers who have done a major upgrade before, time to work through the process, and a test environment. Drupal.org's upgrade documentation describes the steps, and tools such as Upgrade Status and Drupal Rector help identify and fix deprecated code. The harder parts are usually contributed module decisions, custom code that depends on removed or changed APIs, and coordinating two sequential releases while the site stays in production. A partner adds value when those tasks compete with your delivery roadmap or when the team has not run a major upgrade. Either way, document what is done on each version so the second step does not rediscover the first.
Why can't a Drupal 9 site jump straight to Drupal 11?
Drupal does not support skipping a major version during an upgrade. A Drupal 9 site must first move to Drupal 10, then to Drupal 11. The reason is that each major version removes deprecated APIs and changes core behavior that the previous version warned about, and the upgrade path is tested one major version at a time. For the same reason, a Drupal 10 site must stop on Drupal 11 before it can reach Drupal 12. Engineers should plan the intermediate release as a real deployment with its own testing, not a stopover that is only run in a scratch environment.
What happens to Drupal 7 sites that cannot upgrade in one step?
Drupal 7 is not part of the two-version upgrade path. Drupal 7 security support ended on January 5, 2025, according to Drupal.org. Drupal 6 and 7 sites cannot simply be updated to Drupal 10 or later; they are migrated into a new site using the core Migrate, Migrate Drupal and Migrate Drupal UI modules or Drush, and themes must be rebuilt. If your site must keep running while you migrate, the Drupal Association's Extended Security Support Provider Program lists HeroDevs and Tag1 Consulting as certified vendors for that purpose. Ask any provider to confirm the terms and coverage directly, because extended support is a separate commercial arrangement from the upgrade itself.
How do we avoid a second upgrade before Drupal 12?
Start with the end date in mind. Drupal 10 reaches end of life on December 9, 2026, and Drupal 12 is scheduled for the week of December 7, 2026, so a Drupal 10 site has a short window before both events. The practical approach is to move to Drupal 11 with the PHP 8.3 requirement met, fix deprecations that Drupal 12 will also expect, and confirm that every contributed module you depend on has a release for Drupal 11 and is moving toward Drupal 12. Check PHP 8.5 readiness at the same time, because Drupal 12 requires PHP 8.5 or later. Keep custom code on the component and service patterns that survive major releases, and ask any partner to plan the Drupal 11 to 12 step in the same written scope.
How DeployOpen scopes, delivers and supports a multi-version Drupal upgrade
DeployOpen is a Chainscore Labs company that plans, implements, customizes, hardens, documents and supports self-hosted open-source platforms inside the client's own infrastructure. For a Drupal site that has to cross two major versions, we treat each hop as its own tested release with written scope, documented evidence and a plan for keeping the site supported between steps.
How we scope
- We inventory the current Drupal version, PHP version, database and web server before agreeing any version path.
- The written scope lists each intermediate version, the target version and the environments each hop will pass through.
- We review custom modules, themes and contributed projects for compatibility with each version in the sequence.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.
How we build
- We run each major step as a separate branch, with Composer-managed dependencies and a reproducible lock file.
- Deprecated API use in custom code is fixed before moving to the next version, not carried forward.
- Each intermediate version is tested with the same content, configuration and integrations as the previous one.
- Test results, rollback points and database backups are recorded for every hop before it reaches production.
How we hand over
- We deliver a runbook that records each version reached, the date of each cutover and the changes made.
- Configuration, environment variables and deployment steps are documented so your team can repeat the process.
- Known gaps, such as contributed modules without a compatible release, are listed with owners and next steps.
- Knowledge transfer sessions cover the upgrade procedure, rollback steps and how to check the current release.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers after the upgrade is complete.
- A retainer can cover security updates, the next major version and monitoring of the site between releases.
- Ask whether the retainer includes testing against each Drupal security release window and its response times.
- Confirm with us in writing which environments, backups and monitoring tools are covered before signing.

