Don’t go making major version changes

Jakob Perry
Jakob on Drupal
Published in
5 min readAug 12, 2022
Please stick to the minor module versions you’re used to. Credit: https://about.sourcegraph.com/blog/nine-circles-of-dependency-hell

As one of the leads for the Drupal 10 readiness initiative at Acquia, I see a lot of modules. We are looking at the top 165 modules, coupled with another 50 or so modules used by either our products or customers, to ensure they’re ready for Drupal 10.

One theme I’ve observed some maintainers fall into is the idea of contrib major version bumps to work with the next major version of Drupal. However, as I’ll lay out below, this is a major problem for the community and is making it harder for users to get on the latest version of Drupal.

Don’t bump the major unless you absolutely need to

In general, you want to avoid major version changes. (IE: 1.0.0 to 2.0.0 or 8.x-1.x to 2.0.0) This can cause a cascading dependency problem on any downstream module or customer using your module.

Don’t make releases rely on mutually exclusive versions of core

The LTS version of Drupal core should closely match the .0 release of the next version. With few exceptions, your module should always require the current/last supported version and the next or current version of Drupal. When you constrain your release to mutually exclusive versions of core, it narrows the upgrade dependency window a customer can use to upgrade their site. When a module has two different major releases supporting two different versions of core, it makes the dependency tree even harder to follow, creating more opportunity for composer conflicts to occur.

When should I not bump the major version?

Major Drupal core changes. Changing the core version is a major disruption from a dependency standpoint, even if the code doesn’t really change at all. Making your module require a new major version leads to all the dependent modules having to update as well.
Example: The symfony event handler in Drupal 9 changed, which means any module using symfony events cannot be compatible with 8, 9 and 10. Instead of making a new major version, make a new minor version and increase the minimum supported version of core.

Major PHP changes. While the new php features are great, its imperative that developers know what the minimum supported version of PHP is for core. If PHP 8.1 comes out, don’t immediately start using 8.1 only features. The only reason you should ever even require a minimum PHP is because of a needed feature or library included in a newer version of PHP. This was more common in the PHP 5 to 5.4 days, but is increasingly rare today.
Instead, make sure your module is compatible with PHP 8.1, which should still allow it to work with all other versions of PHP at the time of this writing, which is PHP 7.4 and 8.0. Keep in mind that some sites may still be stuck on 7.3, which is still also supported by core.

New features
Any new features that don’t interrupt the existing functionality should be added to the current version. One alternative is bumping the minor version, which will allow most dependent modules to work with your new minor.

To get semantic versioning
Just getting semantic versioning (ie: 8.x-1.x to 2.x) is not a good reason to bump the version. The composer facade included with drupal.org already removes the 8.x portion. I suspect some smaller Drupal 8 modules may never need to move to semantic versioning, unless core or drupal.org mandates it. While it make look pretty and modern, it causes pain for downstream modules and projects.

Incompatible tests
While its important that code has backwards compatibility, even for EOL versions of Drupal, tests only need to support current versions of core. For example, tests written for Drupal 8.9 won’t work in Drupal 10. If your deprecations are mostly within tests, there isn’t a reason to up the version of your module or even compatibility. Drupal 8.9 is EOL and customers shouldn’t expect new module versions to work with old versions of core. But keeping your module technically compatible with earlier versions of core makes it easier for customers to upgrade.

What are some reasons to bump the major version?

Your module’s public services have been rewritten and no longer match the current supported version. This typically occurs when a public method needs to be changed, or the architecture and codeflow of the module is changed significantly that backwards compatibility isn’t feasible. This can also occur if your module extends core classes that become deprecated.
However: Backwards compatibility should always be the goal. Instead of bumping the version to change a public method call, wrap your new call with the old one and mark it deprecated.

Your module’s data model is rewritten in such a way that running simple update scripts aren’t feasible. It requires either reinstalling the module (if data is ephemeral), or migration.
However: Somewhat simple field changes or additions should be done in the same version with code that can interpret the missing change. Dependent modules should never interact directly with data your module owns.

Features are removed or refactored in a way that you want dependent modules to not automatically work with the new version.
Example: Search API Solr 8.x-1.x to 4.x: This uses a different version of solarium, and required the architecture to be rewritten. By making a new release, the old Search API Solr modules could continue to work on old versions.
However: These changes should not be taken lightly, as it requires the maintainer to now maintain two versions of the same module until the dependent modules are updated.

Major contrib module version timing

Never release a new major version within 9 months of a new major core release without planning to upgrade the last major version of your module as well.

While it may seem appealing to update your module’s major version around a major core change, its highly advised not to do that. Typically it takes at least a year for 80%+ of users to adopt the new version, which means you’ll need to support multiple versions for some time, regardless of whether we’re near a new major core release or not.

Each major module version release may have multiple downstream dependencies, public or custom, that need to also be updated. When maintainers bump their major version near the release of a major core version, it adds to the workload of end-users. This is especially tough for smaller orgs where they may have one resource or a periodic contractor updating their site.

If a module plans to have a major release close to a core release, make sure your previous major also supports the new core release as well. This unblocks customers from upgrading core, allowing them to incrementally upgrade their site instead of doing it all at once.

Conclusion

Upgrading to a major version of core is already a difficult task for users. Adding new features or re-architecting your module at the same time adds exponential complexity to an already difficult task.

Changing the major version of a module should not be taken lightly. At a minimum, maintainers should make an issue proposing the change and discuss the reasons for it. If there is a way to keep the module backwards compatible, go that route instead of making a new major version.

--

--