Problem/Motivation

Decide when to defer deprecations in this cycle.

During the Drupal 9.5.x cycle, we tried to defer as many issues with deprecations as possible to 10.1, this meant quite a lot of issues were delayed from landing.

During the 10.x cycle, we deferred deprecations as of 10.3 for removal in 12.0.x. But that was only 9 months before the release of 11.0.0 so a module relying on APIs deprecated in 10.2.x couldn't support both 10.2.x and 11.0.0.

Contrib modules that want to add support for the next major version as early as possible, e.g. when 12.0.0-beta1 is released, should be able to do so without creating a new minor or major branch if it's otherwise unnecessary, to do this, they also need to be able to support minor versions of core that are still security supported when 12.0.0-beta1 is released, which will be 11.2.x and 10.5.x

If we add new APIs in 11.3.x, and deprecate old APIs for removal in 12.0.0, then this reduces the number of modules that can simultaneously support 11.2.x and 12.0.x. However, if we defer disruptive deprecations from 11.3.x onwards for removal to 13.0.0, then in general, 11.2.x and 12.0.0 will have equivalent public APIs.

Steps to reproduce

Proposed resolution

If a deprecation is for @internal code like constructors or plugins, continue to deprecate for removal in 12.x

If a deprecation is for base classes, interfaces, or otherwise likely to affect a lot of modules, deprecate for removal in 13.x

Module/Theme deprecations are allowed - it's actually easier to do these at the end of a major release cycle than earlier on, and while they're slightly disruptive for sites when they update, they're generally not disruptive for contrib or custom modules since the API of the deprecated module stays the same.

There will be lots of edge cases, we can link examples from this issue.

Proposed text for allowed changes. Based on catch's original proposal.

Deprecations

  • disruptive deprecations scheduled for removal in a major release that is more than one year away
  • non-disruptive deprecations scheduled for removal in the next major release

Remaining tasks

Review the draft announcement of the policy.

User interface changes

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#45 Screenshot 2025-06-27 at 5.14.50 AM.png229.61 KBxjm

Comments

quietone created an issue. See original summary.

catch’s picture

The main difference between this and what we did for 10.x-11.x is that we'd start deferring disruptive deprecations one minor release earlier relative to the next major release window. Even though we'd start with 11.3.x and 10.3.x, we have an additional 11.x minor release before 12.0.0 comes out this time due to how the release windows worked out with 9.x/10.x/11.x- which makes this confusing to talk about.

If we start deferring deprecations with the 11.3.x cycle, it means that on the earliest day that 12.0.0 can be released (the June window), the following core branches would have security support:

12.0.x (june 2026)
11.4.x (june 2026)
11.3.x (december 2025)
10.6.x (december 2025, whether we actually branch or continue on 10.5.x is TBD)

The exact EOL date of 10.x is also TBD, but we have the option to commit forward-compatibility fixes to 10.6.x while 11.3.x is in development.

11.2.x security support comes to an end in that June window too, so if there are 11.2.x deprecations that a module needs to deal with, then it may need to drop 11.2.x support when adding 12.0.x support or have two code paths etc. If we miss the June window, then 11.2.x is fully out of the picture too.

This means that at least for straightforward modules, they may be able to support 10.6.x, 11.3.x and 12.0.x with a single branch or at least very minor divergence between minor branches.

We already have annotation and procedural hook deprecations for removal in 13.0.0, either in core or planned very soon, because we know that's going to require a lot of effort to update for, so this is consistent with delaying the removal of those by a major release.

It also means that there should be a finite amount of things to account for in phpstan/rector from June this year.

gábor hojtsy’s picture

I think this is fine, we need to tell the community as soon as possible to give them time to do stuff they were planning quicker now as long as it is possible.

longwave’s picture

Title: Defer disruptive 11.3 deprecations for removal until 13.0 » [policy, no patch] Defer disruptive 11.3 deprecations for removal until 13.0
Status: Active » Needs review

I also have no issue with this, marking NR to get any other feedback from the community.

smustgrave’s picture

Category: Task » Plan

Think it makes sense

If a deprecation is for base classes, interfaces, or otherwise likely to affect a lot of modules, deprecate for removal in 13.x

Sure there will be some learning curves so posting this somewhere may also help. Where I'm not sure as I still find the drupal docs hard to navigate/search.

Where would all the hook deprecations fall under?

catch’s picture

Procedural hooks haven't been deprecated yet. Similarly we haven't deprecated annotation discovery in #3265945: Deprecate plugins using annotations and plugin types not supporting attributes either, I don't think either of those will happen for 11.2, so the earliest they could land is 11.3.

However, although I can't immediately find it, we'd already discussed deferring both of those deprecations for removal in Drupal 13 anyway.

For annotations, there are all of the plugin annotations to convert, but also all the plugin managers need to support attributes before that can happen. So for contrib modules that implement plugins for other contrib modules, there will be chains of 2-3 issues to get it all done. Deferring removal of that to Drupal 13 gives a solid three years for all of that to filter through.

Procedural hooks as a whole I think we would definitely defer removal to Drupal 13 - it's going to affect almost every single contrib and custom module.

But specific hooks like hook_module_implements_alter() we'd probably still remove in Drupal 12 because they have tricky bc layers to deal with, especially if it makes other conversions and clean-up easier to do in Drupal 12.

catch’s picture

Priority: Normal » Major
Status: Needs review » Reviewed & tested by the community

Since there's been no further feedback at needs review, let's see if there's more feedback at RTBC.

nicxvan’s picture

#3481555: [Plan] Determine how to deprecate procedural hooks. is where we discussed procedural hook deprecation.

If I am being honest I'm not sure I see how we can directly deprecate procedural hooks, it will more likely be a side effect of deprecating .module files. There just isn't a clean way to know whether a function is a hook or not. We can throw a message runtime in LegacyHook, but that seems riskier than we would want to be.

Side note, hook_module_implements_alter and hook_hook_info are also strange deprecations because we are just removing them in 12.

kristiaanvandeneynde’s picture

So essentially you get 1 to 1,5 year to adjust to internal deprecations and 3 to 3,5 years for public API deprecations as of 10.3?

The latter seems a bit on the high end if you ask me, but I agree that an absolute minimum of 1 year is too short for contrib and client projects to adapt to disruptive changes. Ideally, we have a 2-year window as a hard cut-off, but trying to align that with major core release dates is tricky.

Essentially you'd have to deprecate things right out the gate when a new major release is cut, which seems impossible unless you postponed deprecations from the last major. And that would essentially be the same deprecating over 2-4 years, but with extra steps.

So with that in mind I suppose RTBC +1, even though I'm not fully a fan of keeping dead weight around for more than 3 years.

catch’s picture

If I am being honest I'm not sure I see how we can directly deprecate procedural hooks, it will more likely be a side effect of deprecating .module files.

Yeah that might be the case. In terms of this issue, we could still deprecate them in any minor version of 11.x, it's just that removal of support would be deferred until 13.0.0

@kristiaanvandeneynde yes it would be 3-3.5 years, although hopefully 3.

Essentially you'd have to deprecate things right out the gate when a new major release is cut, which seems impossible unless you postponed deprecations from the last major. And that would essentially be the same deprecating over 2-4 years, but with extra steps.

Yeah this is what we did with some issues from 8-9 and... exactly.

It wouldn't be only @internal deprecations for removal in Drupal 12, we might decide to deprecate some other things for removal in 12.0.0 if they're low impact on contrib and will cause problems to keep around in core, but the default would be that yes.

larowlan’s picture

+1 from me too

longwave’s picture

In some (hopefully rare) cases we will have no choice: from what I can see at the moment #3522497: Passing an $options array to constraint constructors is deprecated, use named arguments instead is something we are going to have to fix/deprecate in 11.3 for removal in 12, because Symfony is forcing our hand; let's hope that they don't pull off something similar in Symfony 7.4 because then we will have to do the same in 11.4 for removal in 12. In this case it's not particularly disruptive though unless you wrote a bunch of custom constraints, and you would have to upgrade them for Symfony 8 either way.

catch’s picture

I think #12 is fine, if we default to Drupal 13, then in cases where we need to deprecate for removal in Drupal 12 we still can. As long as it's not a change that will affect hundreds of modules then the overall effect is the same.

xjm’s picture

It might be better to talk about "the last minor release before 12.0" or "the minor release accompanying 12.0" because I'm confused myself as to what the actual intent of the IS is. Do we want to start already deferring deprecations right now, possibly a full 18 months before 12.0.0 might be released? That seems extreme to me. It could be three entire minors.

xjm’s picture

That said, I would definitely defer deprecations on a case-by-case basis (e.g., I would not deprecate procedural hooks for removal in 12.0.0 no matter what!).

catch’s picture

@xjm the main reason is so that a module that's compatible with 11.2 and 10.5, with all deprecated usages fixed, has a decent chance of also being compatible with 12.0.0 assuming it comes out in June.

If there are new removals due to APIs added in 11.3, it makes it harder for modules to add 12.x support at the earliest possible point (during beta/rc or earlier), this is something @berdir has brought up during previous major release cycles iirc.

Even though those three releases won't be supported at the same time, 12.0.0-beta1/rc1 etc will come out before support is dropped for 11.2 if the first window is hit.

We'd still be able to deprecate things for 12.x if there's a good reason to, just the default would be for removal in 13.x

Contrib modules and best effort BC layers in @internal code etc. would all still be for 12.x too.

I thought I'd put all this in the issue summary but it's mostly in the first comment instead. This is mostly assuming we have a decent chance of hitting the June release window which I think we do at the moment.

xjm’s picture

It would be good for that to move into the IS, which explains the "what" but not the "why". It sounds like we want to enable contrib developers to decouple when they do their upgrades from when core does theirs, is that the idea? In the same way that the branch support lets site owners.

Edit: After further discussion in Slack and reviewing the issues, I came to understand that the core problem here is something we discussed years back, that in a June release scenario 12.0.0-beta1 may be tagged while 11.2.x still has security coverage, putting contrib developers in an impossible situation where they need to address deprecations for D12 for the upcoming release but also still need to support 11.2.x and have to resort to multiple branches or complex conditional code. I corrected this later elsewhere, but just editing this comment so as not to distract. :)

It would be good for the IS to state it as "for the branch for the December minor release in the odd years" or something. (The last minor prior to the one that accompanies the major.)

xjm’s picture

 

xjm’s picture

Status: Reviewed & tested by the community » Needs review

Also if we're going to announce this to people (which @gábor hojtsy suggests and is a good idea) I would like to be able to make a compelling case for why, so that's a reason to actually do the work here I think.

I know it might feel like a rush now since 11.x is already including new deprecations not present in 11.2.x, but we can also internally ask the committer team to check with the team about disruptive deprecations they want to backport while this policy discussion is open.

xjm’s picture

There is also a much older policy discussion somewhere about the struggle for contrib to support the last two months for the security-supported branch at the same time as the betas for the major. Can we add that to the related issues? It might have good context.

xjm’s picture

Status: Needs review » Needs work

Meant this, for IS updates and a "why" statement.

catch’s picture

Issue summary: View changes
Status: Needs work » Needs review

Added some notes to the issue summary.

quietone’s picture

Trying for plain english on the policy language:

The last version for a disruptive deprecation is the minor release one year before the first release window for a next major release. The first release window may be in June, August or December as outlined in the release process overview.

After that, a disruptive deprecation will be scheduled for removal in the major release two major releases ahead instead of one.

This allows more modules to support the next major release and the currently supported minor releases.

or

A disruptive deprecation is allowed up to, and including, the minor release one year before the first release window for a next major release. The first release window may be in June, August or December as outlined in the release process overview.

After that minor release, a disruptive deprecation will be scheduled for removal in the major release two major releases ahead instead of one.

This allows more modules to support the next major release and the currently supported minor releases

catch’s picture

The only issue I have with both of those versions is it's not clear what the difference is before/after the cut-off, e.g. it doesn't explicitly say that deprecations are removed in the next major release at first.

quietone’s picture

Is this better? Adding the extra detail does make the sentence harder to read but it is still correct.

A disruptive deprecation scheduled for removal in the next major release is allowed up to, and including, the minor release one year before the first release window for a next major release. The first release window may be in June, August or December as outlined in the release process overview.

After that minor release, a disruptive deprecation will be scheduled for removal in the major release two major releases ahead instead of one.

This allows more modules to support the next major release and the currently supported minor releases

I presume this would go some where in the allowed changes.

catch’s picture

#25 looks good, it's not particularly easy to read but this is not exactly a straightforward thing to explain.

quietone’s picture

Issue summary: View changes

Thanks. Yes, it isn't easy to explain this one. I moved that proposal to the issue summary. I'd be OK with adding this text, assuming we all agree it is accurate, and tweaking it later.

Are #17 and #18 addressed?

nicxvan’s picture

Could we flip it and say something like disruptive deprecations within a year of the next major must skip that major for removal?

catch’s picture

Maybe this?

"Disruptive deprecations added to minor branches within one year of the next major release should schedule the removal of that deprecation one additional major release ahead. This allows more modules to support the next major release and the currently supported minor releases."

nicxvan’s picture

That reads much clearer to me!

quietone’s picture

Issue summary: View changes

Nice! I added the proposal from #29 to the issue summary.

xjm’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs issue summary update

Great suggestion @nicxvan!

I'm completely comfortable with the updated IS and the new proposed policy text, so re-TBCing.

nicxvan’s picture

Now we just need to define disruptive.

xjm’s picture

@nicxvan, several points:

  1. The issue summary already outlines examples.
  2. We already have a definition of disruptive changes in our core allowed changes policy.
  3. Ultimately, it's at the release managers' discretion.

So that is not an outstanding task; the committers will handle it as issues come up for commit or at contributors' request for feedback. :) Hope that helps!

quietone’s picture

There is agreement on the change so I added the proposed text to the 'allowed changes' policy.

nicxvan’s picture

Thanks!

xjm’s picture

Hm, the quoted text did not fit the style/organization of the section it was added, which was a list of specific types of changes allowed in minor releases. I rewrote it as:

Deprecations

  • disruptive deprecations scheduled for removal in a major release that is more than one year away.
  • non-disruptive deprecations scheduled for removal in the next major release.

(The changed text in context.)

If we still want the longer sentence and justification proposed in the IS, it should be in a higher-level policy page. Or maybe what I have is enough?

quietone’s picture

Issue summary: View changes

I updated the issue summary with the new text that is on the allowed changes policy.

The extra sentence could be incorporated into https://www.drupal.org/about/core/policies/core-change-policies/continuo...

xjm’s picture

https://www.drupal.org/about/core/policies/core-change-policies/continuo... does indeed look like the right place (although I think overall the page could use a bit more work as even I don't know what some of it means, oops). Maybe after this paragraph:

When a new API is added, the old API is deprecated. The old API will not be removed in the current major release. The old API is removed in a future major release.

We could actually use @catch's original text there (reworded a bit to make the sentences simpler):

When a new API is added, the old API is deprecated. The old API will not be removed in the current major release. The old API is removed in a future major release.

When a disruptive deprecation is added to a minor branch within one year of the next major release, it should schedule the removal of the old API one additional major release ahead. This allows more modules to support the next major release and the currently supported minor releases.

quietone’s picture

That text works for me.

And yes, the policy could use some rewording.

xjm’s picture

Status: Reviewed & tested by the community » Fixed

I added the content to the handbook page (and added at least some subheaders while I was at it for scannability).

I think we can call this fixed now. Thanks everyone!

xjm’s picture

Status: Fixed » Reviewed & tested by the community

Wait, sorry, we still need that announcement.

berdir’s picture

Looks great. Should we link the word disruptive again to the chapter below on the same page: https://www.drupal.org/about/core/policies/core-change-policies/allowed-... ? I was wondering if that might also need some updates. For example, it has both "Will require widespread documentation" *and* "Will require documentation updates.". I think the second sentence is redundant and pretty much any change comes the need for *some* documentation updates, only *widespread* updates makes it disruptive?

Personally, I'd also add a sentence there that in the end, whether or not something is (too) disruptive is something that core maintainers decide because there are going to be exceptions, like the example in #12.

xjm’s picture

@berdir:

Looks great. Should we link the word disruptive again to the chapter below on the same page: https://www.drupal.org/about/core/policies/core-change-policies/allowed-... ?

I did actually! I just didn't put it in the quoted text. :)

I was wondering if that might also need some updates. For example, it has both "Will require widespread documentation" *and* "Will require documentation updates.". I think the second sentence is redundant and pretty much any change comes the need for *some* documentation updates, only *widespread* updates makes it disruptive?

Ah. I think the second is like user guide updates, whereas the first is "invalidating current MRs". Which one only knows if one is the person who Angie or Jennifer or whoever talked to about it in 2013 or something. We could say "handbook or user documentation updates"? Maybe scope creep, though. OTOH maybe not; if we take the hook deprecations as our litmus, those definitely make the leap from API docs to actual guidebook-level docs and would be disruptive on that basis alone. (It's supposed to be also about things like user screenshots and stuff though, IIRC from a decade-plus ago.)

Personally, I'd also add a sentence there that in the end, whether or not something is (too) disruptive is something that core maintainers decide because there are going to be exceptions, like the example in #12.

This would be practically every other sentence in every release policy, doc, though. :) Every policy is "or at committer discretion", and for every release policy that's followed by "with release managers making the final decision for the allowed versions".

xjm’s picture

Issue summary: View changes
StatusFileSize
new229.61 KB

Did this for now :
screenshot showing the revision log for the allowed changes policy

Since it's an appendix about disruptions, seems fair to mention at the end re: who makes the decision on the term's definition.

xjm’s picture

Issue tags: +Needs community announcement

Shockingly, there is no "Needs" issue tag for a community announcement (I searched the whole vocabulary admin listing), so inaugurating one.

xjm’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: -Needs community announcement

I wrote a draft announcement for this policy. It actually starts by announcing that D10 is officially EOL in December 2026 now, because we hadn't officially announced that yet but I needed to refer to it.

xjm’s picture

Issue summary: View changes

 

nicxvan’s picture

There are two places that say

Disruptive deprecations should now be scheduled for removal before Drupal 13.0.0

Should be removal in Drupal 13

Not before Drupal 13

xjm’s picture

Right, sorry, I forgot that we changed our language for that (for the better). Fixing.

nicxvan’s picture

Thank you, looks great now. I couldn't see how to make a suggestion from my phone which is why I posted here.

joseph.olstad’s picture

The number 13 is often skipped and is widely considered bad luck. Buildings (especially in Canada), the vast majority of our buildings go from 12th floor to the 14th floor as very few people actually want to rent or live on the 13th floor! Humour aside, #49, #50, #51 is a massive improvement , thanks!

quietone’s picture

Status: Needs review » Reviewed & tested by the community

The allowed changes policy is updated and the post published.

longwave’s picture

Status: Reviewed & tested by the community » Fixed

Thanks everyone, there is nothing left to do here that I can see, so marking fixed.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.