Skip to content

Commit 4c2ceab

Browse files
committed
docs(adr): add ADR 002 for MSRV policy
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.
1 parent 09b85b5 commit 4c2ceab

2 files changed

Lines changed: 176 additions & 0 deletions

File tree

docs/adr/002_msrv_policy.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# MSRV (Minimum Supported Rust Version) Policy
2+
3+
## Date
4+
5+
20 Feb 2026
6+
7+
## Summary
8+
9+
This ADR proposes replacing the current "N-3" version-count MSRV policy with a
10+
12-month trailing window. Under this policy, the MSRV may be raised to any
11+
stable Rust release whose release date is at least 12 months prior to the date
12+
the MSRV bump PR is opened. This applies uniformly across all published
13+
workspace crates. MSRV bumps are not considered semver-breaking changes.
14+
15+
## Motivation
16+
17+
The current MSRV policy states that "the current stable Rust compiler and the
18+
three most recent minor versions before it will always be supported." Given
19+
Rust's 6-week release cadence, N-3 equates to roughly 4.5 months — but the
20+
actual MSRV (1.75, released December 2023) is over two years old as of this
21+
writing. The stated policy and practice are misaligned.
22+
23+
A time-based policy addresses this in a few ways:
24+
25+
- It is easier to reason about. Users and maintainers can determine eligibility
26+
from a release date without needing to know Rust's release cadence or the
27+
current stable version number.
28+
- It is more predictable for downstream consumers. A 12-month window gives
29+
library authors and end users a full year to upgrade their toolchain before
30+
they are affected.
31+
- It aligns with the broader Rust ecosystem. The most widely-adopted formal
32+
MSRV policies in the Rust ecosystem are time-based (see
33+
[Ecosystem Context](#ecosystem-context) below).
34+
- It is consistent with OpenTelemetry cross-language guidance. The OpenTelemetry
35+
specification states: "Each language implementation SHOULD define how the
36+
removal of a supported language/runtime version affects its versioning. As a
37+
rule of thumb, it SHOULD follow the conventions in the given ecosystem."
38+
([source](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md#language-version-support))
39+
40+
## Policy
41+
42+
### The rule
43+
44+
The MSRV may be raised to any stable Rust version whose release date is at
45+
least 12 months prior to the date the MSRV bump PR is opened.
46+
47+
### Scope
48+
49+
A single, uniform MSRV applies to all published crates in the workspace.
50+
Examples, stress tests, and internal test crates are excluded.
51+
52+
### Semver treatment
53+
54+
MSRV bumps are not semver-breaking changes. They are shipped in minor releases
55+
only, never in patch releases.
56+
57+
The `rust-version` field in each crate's `Cargo.toml` is the source of truth
58+
and must be kept in sync across the workspace.
59+
60+
### CI enforcement
61+
62+
CI must verify compilation against the declared MSRV on every PR. The MSRV CI
63+
job should use a pinned toolchain (e.g. `+1.85.0`) and run at minimum
64+
`cargo check --all-features` against all published crates.
65+
66+
### Process for bumping the MSRV
67+
68+
1. Open a PR that updates the `rust-version` field in all published workspace
69+
`Cargo.toml` files.
70+
2. Verify that the target Rust version was released at least 12 months ago.
71+
3. The PR description should note what the bump enables (dependency removal,
72+
new std APIs, edition upgrade, etc.). This context is informational and
73+
helps reviewers — it is not a gate.
74+
4. Standard review and approval process applies.
75+
76+
## Practical impact
77+
78+
Under this policy the MSRV could immediately move from 1.75 (December 2023) to
79+
1.85 (February 2025), which would enable:
80+
81+
- Replacing `once_cell`, `lazy_static`, `num-format`, and `num_cpus` with std
82+
APIs (`LazyLock`, `available_parallelism`).
83+
- `#[expect(lint)]` (stable in 1.81) — works like `#[allow]` but warns when
84+
the suppressed lint stops firing, preventing stale suppressions from
85+
accumulating.
86+
- `core::error::Error` (stable in 1.81) — the `Error` trait in `core`
87+
strengthens the `no_std` story.
88+
- Edition 2024 eligibility — Rust 1.85 is the minimum version for Edition
89+
2024, which brings the MSRV-aware dependency resolver (resolver v3),
90+
stricter `unsafe_op_in_unsafe_fn` defaults, and improved lifetime capture
91+
rules.
92+
93+
For reference, here is what the 12-month window looks like over time:
94+
95+
| Date | Current Stable | 12-Month Window Allows |
96+
|------|---------------|------------------------|
97+
| Feb 2026 (today) | 1.93 | 1.85 (Feb 2025) |
98+
| Aug 2026 | ~1.98 | 1.89 (Aug 2025) |
99+
| Feb 2027 | ~1.102 | 1.93 (Jan 2026) |
100+
101+
## Ecosystem context
102+
103+
### Rust ecosystem
104+
105+
The most widely-used Rust crates with formal, documented MSRV policies use a
106+
time-based or version-count approach:
107+
108+
| Project | Documented Policy | Window |
109+
|---------|-------------------|--------|
110+
| [tokio](https://github.com/tokio-rs/tokio#supported-rust-versions) | "The new Rust version must have been released at least six months ago" | 6 months |
111+
| [hyper](https://github.com/hyperium/hyper/blob/master/docs/MSRV.md) | "A compiler version released within the last 6 months can compile hyper" | 6 months |
112+
| [tower](https://github.com/tower-rs/tower#supported-rust-versions) | "The new Rust version must have been released at least six months ago" | 6 months |
113+
| [tracing](https://github.com/tokio-rs/tracing#supported-rust-versions) | "The current stable Rust compiler and the three most recent minor versions before it will always be supported" | N-3 |
114+
115+
Our proposed 12-month window is twice as conservative as the 6-month policy
116+
used by tokio, hyper, and tower, reflecting opentelemetry-rust's role as
117+
infrastructure depended on by downstream libraries and instrumentation.
118+
119+
### OpenTelemetry language SDKs
120+
121+
Other OpenTelemetry language SDKs handle minimum version support as follows:
122+
123+
| Language | Minimum | Policy |
124+
|----------|---------|--------|
125+
| [Go](https://github.com/open-telemetry/opentelemetry-go#compatibility) | Go 1.24 | Follows upstream Go support: "each major Go release is supported until there are two newer major releases" |
126+
| [Python](https://github.com/open-telemetry/opentelemetry-python#python-version-support) | Python 3.9 | "We remove support for old Python versions 6 months after they reach their end of life" |
127+
| [Node.js](https://github.com/open-telemetry/opentelemetry-js#supported-runtimes) | Node.js 18 | "Only Node.js Active or Maintenance LTS versions are supported" |
128+
| [.NET](https://github.com/open-telemetry/opentelemetry-dotnet#supported-net-versions) | net462 | "All the officially supported versions of .NET and .NET Framework (except .NET Framework 3.5)" |
129+
| [Java](https://github.com/open-telemetry/opentelemetry-java/blob/main/VERSIONING.md#language-version-compatibility) | Java 8 | "Changing requires major version bump" |
130+
131+
The common pattern across OTel SDKs is to follow the conventions of each
132+
language's ecosystem. Rust does not have a concept of upstream EOL for compiler
133+
versions, so a time-based trailing window is the closest analog to the
134+
lifecycle-based policies used by Go, Python, and Node.js.
135+
136+
## Alternatives considered
137+
138+
### 6-month trailing window
139+
140+
This is the de facto standard among the most widely-used Rust crates (tokio,
141+
hyper, tower). It would allow faster adoption of new language features.
142+
143+
We did not go with this because opentelemetry crates are infrastructure —
144+
depended on by downstream libraries and instrumentation across the ecosystem.
145+
A 6-month window, while common for application-oriented crates, is more
146+
aggressive than appropriate for a project whose MSRV bumps ripple outward
147+
through transitive dependencies.
148+
149+
### N-3 version-count (current policy)
150+
151+
The existing documented policy supports the current stable Rust compiler and
152+
the three most recent minor versions before it. This is equivalent to roughly
153+
4.5 months given Rust's 6-week release cadence.
154+
155+
There are two problems with keeping this policy:
156+
157+
1. It is paradoxically more aggressive than 6-month policies while being
158+
perceived as conservative. N-3 allows bumping to a version that may be only
159+
~4.5 months old.
160+
2. The policy and practice are misaligned. The current MSRV (1.75) is over
161+
two years old while the N-3 policy would currently allow up to 1.90 (with
162+
stable at 1.93). This gap suggests the policy does not reflect how the
163+
project actually manages MSRV in practice.
164+
165+
A 12-month window is genuinely more conservative than both alternatives while
166+
still allowing the project to benefit from language improvements within a
167+
reasonable timeframe.
168+
169+
## References
170+
171+
- [PR #3352 — Bump MSRV to 1.85](https://github.com/open-telemetry/opentelemetry-rust/pull/3352) — the discussion that motivated this ADR
172+
- [OpenTelemetry specification — Language version support](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/versioning-and-stability.md#language-version-support)
173+
- [Rust RFC 2495 — `rust-version` in Cargo.toml](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)
174+
- [Rust RFC 3537 — MSRV-aware resolver](https://rust-lang.github.io/rfcs/3537-msrv-resolver.html)
175+
- [Rust release history](https://releases.rs/)

docs/adr/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
This directory contains architectural decision records made for the opentelemetry-rust project. These allow us to consolidate discussion, options, and outcomes, around key architectural decisions.
44

55
* [001 - Error Handling](001_error_handling.md)
6+
* [002 - MSRV Policy](002_msrv_policy.md)

0 commit comments

Comments
 (0)