|
| 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/) |
0 commit comments