Skip to content

docs(adr): propose 12-month trailing window MSRV policy#3361

Open
bryantbiggs wants to merge 2 commits intoopen-telemetry:mainfrom
bryantbiggs:rfc/msrv-policy
Open

docs(adr): propose 12-month trailing window MSRV policy#3361
bryantbiggs wants to merge 2 commits intoopen-telemetry:mainfrom
bryantbiggs:rfc/msrv-policy

Conversation

@bryantbiggs
Copy link
Contributor

Summary

Proposes replacing the current N-3 version-count MSRV policy with a 12-month trailing window via a new ADR (docs/adr/002_msrv_policy.md).

  • The MSRV may be raised to any stable Rust version that is at least 12 months old
  • A single uniform MSRV applies across all published workspace crates
  • MSRV bumps are not semver-breaking and are shipped in minor releases only

Context

This was requested during the discussion on #3352. The ADR includes:

  • Ecosystem research showing tokio, hyper, and tower all use a 6-month rolling window — our 12-month proposal is twice as conservative
  • A survey of how other OTel language SDKs (Go, Python, Node.js, .NET, Java) handle minimum version policies, with links to each project's documented policy
  • Two alternatives considered (6-month window and the current N-3 policy) with rationale for why 12 months is the better fit for an infrastructure crate

Practical impact

Under this policy the MSRV could immediately move from 1.75 (December 2023) to 1.85 (February 2025), enabling removal of once_cell, lazy_static, num-format, and num_cpus in favor of std APIs, plus eligibility for Edition 2024 and the MSRV-aware dependency resolver.

Merge requirement checklist

  • CONTRIBUTING guidelines followed
  • Unit tests added/updated (if applicable)
  • Appropriate CHANGELOG.md files updated for non-trivial, user-facing changes
  • Changes in public API reviewed (if applicable)

Propose replacing the current N-3 version-count MSRV policy with a
12-month trailing window. The MSRV may be raised to any stable Rust
release that is at least 12 months old. This is more conservative than
the 6-month policy used by tokio, hyper, and tower, reflecting
opentelemetry-rust's role as infrastructure.

Motivated by the discussion in open-telemetry#3352.
@codecov
Copy link

codecov bot commented Feb 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.7%. Comparing base (09b85b5) to head (b3ad92d).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##            main   #3361     +/-   ##
=======================================
+ Coverage   82.2%   82.7%   +0.4%     
=======================================
  Files        128     128             
  Lines      24626   24811    +185     
=======================================
+ Hits       20267   20526    +259     
+ Misses      4359    4285     -74     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@scottgerring
Copy link
Member

Hey @bantonsson and @paullegranddc ; for one helpful downstream anecdote - do we have a view on the Datadog side on MSRV? I note that dd-trace-rs is up at 1.84 vs the current MSRV of 1.75.

Also @open-telemetry/rust-approvers I think we also need to carefully consider what our MSRV policy should be.

On the one hand it feels like we are quite out of date and as @bryantbiggs has pointed out this has led to us missing out on some pieces on std we could otherwise leverage, on the other, I expect that it is healthy for us to aim to drag our MSRV window out for as long as possible. Said otherwise, perhaps rather than promising to advance it, we should promise not to advance it, outside of reasons $X,Y,Z ?

I will also share this in the slack to try solicit feedback !


## Ecosystem context

### Rust ecosystem
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

despite their documented policy, they are all actually quite conservative and some are on 1.6* today.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is correct!

@lalitb
Copy link
Member

lalitb commented Feb 20, 2026

The ADR is well-researched, but I think we should be careful about the gap between policy and practice.

The ADR cites tokio (6-month policy), hyper (6-month), and tower (6-month) as precedent. But their actual MSRVs tell a different story:

Crate Stated Policy Actual MSRV Age
tokio 6 months 1.71 ~2 years
hyper 6 months 1.63 ~3 years
tower 6 months 1.64 ~3 years
tonic 1.75 ~2 years

Even projects with aggressive policies bump conservatively in practice. We should learn from that.

I'm supportive of documenting a guideline, but I'd prefer it to be framed as a recommendation rather than a policy that gets mechanically enforced. The 12-month window should communicate what's permissible to the community, not create an expectation that bumps will happen on a schedule. Maintainers should still exercise judgment - bumps should be motivated by concrete need (blocking dependency, std API replacing an external crate, security fix), not just because the window allows it.

I'd also suggest separating the guideline from the actual bump. There's no urgency to bump right now.

@scottgerring
Copy link
Member

@lalitb @cijothomas could we consider framing this in terms of what would cause us to bump?

@bryantbiggs
Copy link
Contributor Author

The ADR is well-researched, but I think we should be careful about the gap between policy and practice.

The ADR cites tokio (6-month policy), hyper (6-month), and tower (6-month) as precedent. But their actual MSRVs tell a different story:
Crate Stated Policy Actual MSRV Age
tokio 6 months 1.71 ~2 years
hyper 6 months 1.63 ~3 years
tower 6 months 1.64 ~3 years
tonic — 1.75 ~2 years

Even projects with aggressive policies bump conservatively in practice. We should learn from that.

Correct, see @cijothomas 's comment on this already above. and more to this point below

I'm supportive of documenting a guideline, but I'd prefer it to be framed as a recommendation rather than a policy that gets mechanically enforced. The 12-month window should communicate what's permissible to the community, not create an expectation that bumps will happen on a schedule. Maintainers should still exercise judgment - bumps should be motivated by concrete need (blocking dependency, std API replacing an external crate, security fix), not just because the window allows it.

agreed, thats what the rule states:

The MSRV may be raised to any stable Rust version whose release date is at least 12 months prior to the date the MSRV bump PR is opened.

Emphasis on may be raised - not that it will, nor automatically. and to the point about the projects policy vs MSRV - again, this is just the policy. we aren't stating that the MSRV is changing today, this is just the policy and that is why the references and data are included. However, if you do look at those projects, you'll see there is churn happening with wanting to adopt a later version to enable newer APIs and functionality - what is not clear is what is holding that up (most likely, concerns that have been raised by others here). So the what we should take away is - we can see what others have for a policy, but they are not truly following it. Why? Most likely due to its effect on their users. This is why I have not proposed the same policy, but something in between - so that we can follow it instead of just stating a policy but holding the MSRV much lower than the policy allows (whats the point of the policy then?)

I'd also suggest separating the guideline from the actual bump. There's no urgency to bump right now.

I don't quite follow - could you elaborate? there are no version bumps happening here, just the proposal of what policy the project might adopt for how it handles raising the MSRV

@lalitb
Copy link
Member

lalitb commented Feb 20, 2026

You're right that the ADR says "may" not "will" - I was reacting more to the "Practical impact" section which seems to be read as "here's what we'd do immediately." That framing made it feel like the policy and the first bump were being proposed together. I'd suggest reframing that section to read as illustrative rather than prescriptive. Something like:

Practical impact

As an example, if this policy were adopted today, the 12-month window would permit raising the MSRV up to 1.85 (February 2025). Some capabilities that would become available at various MSRV levels
include:

  • 1.80+: std::sync::LazyLock - could replace once_cell / lazy_static
  • 1.81+: #[expect(lint)], core::error::Error
  • 1.85+: Edition 2024 eligibility (MSRV-aware resolver, stricter unsafe_op_in_unsafe_fn defaults)

Any actual MSRV bump would be proposed and evaluated separately based on concrete need at the time.

This keeps the section useful as context without implying an immediate bump to 1.85. It also avoids the num_cpus/num-format claims - num_cpus could already be replaced at 1.75
(available_parallelism was stabilized in 1.59), and num-format may not be in the dependency tree (not sure through).

"what is not clear is what is holding that up... So what we should take away is - we can see what others have for a policy, but they are not truly following it. Why?"

On the "why not follow the policy" question - I think the answer for tokio et al. is simply that the cost of bumping (downstream churn) usually outweighs the benefit unless there's a concrete motivator. The policy exists as a social contract ("we won't go newer than X"), not as a schedule. I think we're actually aligned here - I just want to make sure the ADR text reads that way to future contributors who might interpret a 12-month window as encouragement to bump proactively.

The 12-month window as a ceiling is reasonable. No objections to the policy itself.

@lalitb
Copy link
Member

lalitb commented Feb 20, 2026

@lalitb @cijothomas could we consider framing this in terms of what would cause us to bump?

+1 we should do that.

@bryantbiggs
Copy link
Contributor Author

we can update the language to make the language a bit clearer on "it could happen, its not guaranteed to happen just for the sake of a bump". And to Scott's point - perhaps a bit more definition around - "these are valid reasons to bump the MSRV" maybe something on some examples of whats not a fruitful, meaningful reason to bump.

For example, getting to the next rust edition seems like a plausible reason to bump. its just a matter of how we phrase it so we don't get too overly pedantic on "if this yes, if this no" for every situation

@cijothomas
Copy link
Member

My only comment is: despite promising to support N to N-3 rust versions, we were quite conservative so far. (similar in tokio/tracing etc.)

Previous bumps to MSRV did not receive any pushbacks (nothing I can find in this repo, or slack or personal conversations)

#1554 has suggested to follow "forrecene", but they are well past 1.89 already.

@lalitb mentioned earlier about Debian supported Rust versions, but we broken them already with our bump to 1.75 a year ago, and no issue was reported here.

IOW, I am supportive of actually following the established policy and also the change the policy to what this proposes. If there are any issues that I am not seeing, happy to revise position.

@cijothomas
Copy link
Member

@djc I know you are not active here anymore, but we could use some insights from you on this topic given your expertise, provided you have bandwidth! Thanks in advance.

@djc
Copy link
Contributor

djc commented Feb 25, 2026

Happy to vent my opinions:

I mostly agree with what's being said. If you want to be a low-level (in the sense of a multiple-hop-transitive dependency of actual applications) library, especially one that might be depended on by other libraries (some of which are also low-level), it's important not to unnecessarily increase constraints on your downstreams. This may not be the same for all components in this repo -- the opentelemetry crate might be considered what's sometimes called a "vocabulary" crate, which might appear in downstream public API, while something like opentelemetry-jaeger-propagator is arguably a higher-level dependency that probably will usually be a direct application dependency.

For low-level libraries, IMO MSRV bumps need to be well motivated, in that I usually prefer not to make changes unless there's substantial benefit to my downstream users (which might be different from there being benefit to me as a maintainer). One benefit might be upstream dependency deduplication -- that is, I might want to bump my MSRV so that I can pick up the latest semver-incompatible version of my dependency, which helps deduplicate dependencies for all of my downstreams. On the other hand, I will usually version my Cargo.lock and hold back semver-compatible dependencies if there's a semver-compatible MSRV bump, because in that case bumping my MSRV does not actually benefit my downstreams).

So my main goal generally (similar to what some of you have already pointed out) is that MSRV bumps need to be justified by some benefit, so something like this is useful:

  • 1.80+: std::sync::LazyLock - could replace once_cell / lazy_static

This is a minor benefit, and probably not something I'd bump for. I'd also hope you have already dropped lazy_static in favor of once_cell everywhere to minimize dependencies, and that you're not exposing once_cell in public API (this is generally a concern for most upstreams that aren't themselves 1.x yet).

  • 1.81+: #[expect(lint)], core::error::Error

IMO this is more of a benefit, particularly if you have some no_std API (might be worth doing alloc-only for some of the core crates).

  • 1.85+: Edition 2024 eligibility (MSRV-aware resolver, stricter unsafe_op_in_unsafe_fn defaults)

IMO the 2024 edition isn't all that desirable in most (library) contexts -- the MSRV aware resolver is not a benefit for libraries, only for applications, AFAICT, so I wouldn't bump for this.

The other factor of course is support across your users. For example, Debian stable support might be a factor -- trixie (which has been out for 7 months or so) includes 1.85, so that might not be a blocker in this case. Here's some actual data:

image

(Although this data might be skewed away from older versions due to various factors.)

FWIW, for a bunch of the projects I maintain we picked 1.83 as a reasonable goal now. For the reasons explained, I think being conservative is a good default (definitely not picking up the most aggressive MSRV just because your policy allows it) and then bumps should come with compensating downstream benefits.

Hope that helps.

@paullegranddc
Copy link
Contributor

@djc Hey, where does your data come from, and is it publicly available? It seems super interesting and I couldn't find this kind of statistics when I looked for them some time ago.

@djc
Copy link
Contributor

djc commented Feb 25, 2026

- Add "When to bump" section: bumps need concrete downstream benefit,
  window is a ceiling not a schedule
- Rewrite "Practical impact" as illustrative (what levels enable) rather
  than prescriptive (what we'd do immediately)
- Remove inaccurate num_cpus/num-format claims and MSRV-aware resolver
  selling point (only benefits applications, not libraries)
- Add "Actual MSRV" column to ecosystem table showing policy-vs-practice
  gap in tokio/hyper/tower
- Soften N-3 alternatives section to acknowledge practice divergence
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants