Context
StackExchange.Redis 3.x is available (latest: 3.0.11). The library currently depends on SE.Redis 2.12.14.
SE.Redis 3.0 is an internal IO rewrite with no intentional API breaking changes — it is described as a "direct mirror" of 2.13.17 but with a new IO core using RESP3 by default. The only behavioral change is that Execute[Async] now enforces AllowAdmin for admin commands. Performance improvements are significant (2x+ on LRANGE workloads).
Problem
Consumers of StackExchange.Redis.Extensions may reference either SE.Redis 2.x or 3.x in their projects. The NuGet dependency resolution behavior creates two scenarios:
-
We ship with SE.Redis 2.x dependency — consumers using SE.Redis 3.x get it resolved via binding redirect / assembly unification. This works only if 3.x is truly API-compatible (no removed types, no signature changes). If any APIs diverge in a future 3.x minor, this breaks at runtime.
-
We ship with SE.Redis 3.x dependency — consumers still on 2.x are forced to upgrade, which may not be possible if they depend on 2.x-specific internal behavior or haven't validated 3.x in their infrastructure.
Neither option is safe for all consumers.
Proposed approach
Option A: Widen the version range (preferred if API-compatible)
Since SE.Redis 3.0 has no API changes, update the PackageReference to use a version range that accepts both:
<PackageReference Include="StackExchange.Redis" Version="[2.12.14,)" />
This allows NuGet to resolve either 2.x or 3.x based on what the consumer has in their project. Our code compiles against the 2.x API surface which is a subset of 3.x.
Risks:
- If a future SE.Redis 3.x release introduces API changes, our library would compile fine (against 2.x) but fail at runtime when 3.x introduces type/method signature changes
- RESP3 default in 3.x could surface behavioral differences in edge cases (e.g.,
SUBSCRIBE command responses)
Mitigation:
- Run our test suite against both SE.Redis 2.12.x and 3.0.x in CI (matrix build)
- Pin upper bound if needed:
[2.12.14, 4.0.0)
Option B: Dual packages
Publish two variants of the Core package:
StackExchange.Redis.Extensions.Core → SE.Redis 2.x
StackExchange.Redis.Extensions.Core.v3 → SE.Redis 3.x
Pros: explicit, no surprises.
Cons: doubles the package matrix (Core × Serializers × Compressors), maintenance burden is high.
Option C: Major version bump
Release StackExchange.Redis.Extensions 13.x targeting SE.Redis 3.x only. Keep 12.x on SE.Redis 2.x for consumers who can't upgrade.
Pros: clean separation, follows semver.
Cons: forces a major version bump for what is essentially a transparent dependency upgrade; requires maintaining two branches.
Recommended next steps
- Run the full test suite against SE.Redis 3.0.11 locally to verify API compatibility
- If tests pass, adopt Option A with upper bound
[2.12.14, 4.0.0) and add a CI matrix for both versions
- Document the supported SE.Redis version range in README
- If any test fails, evaluate whether it's a behavioral difference or an actual API break, and fall back to Option C
Context
StackExchange.Redis 3.x is available (latest: 3.0.11). The library currently depends on SE.Redis 2.12.14.
SE.Redis 3.0 is an internal IO rewrite with no intentional API breaking changes — it is described as a "direct mirror" of 2.13.17 but with a new IO core using RESP3 by default. The only behavioral change is that
Execute[Async]now enforcesAllowAdminfor admin commands. Performance improvements are significant (2x+ onLRANGEworkloads).Problem
Consumers of StackExchange.Redis.Extensions may reference either SE.Redis 2.x or 3.x in their projects. The NuGet dependency resolution behavior creates two scenarios:
We ship with SE.Redis 2.x dependency — consumers using SE.Redis 3.x get it resolved via binding redirect / assembly unification. This works only if 3.x is truly API-compatible (no removed types, no signature changes). If any APIs diverge in a future 3.x minor, this breaks at runtime.
We ship with SE.Redis 3.x dependency — consumers still on 2.x are forced to upgrade, which may not be possible if they depend on 2.x-specific internal behavior or haven't validated 3.x in their infrastructure.
Neither option is safe for all consumers.
Proposed approach
Option A: Widen the version range (preferred if API-compatible)
Since SE.Redis 3.0 has no API changes, update the
PackageReferenceto use a version range that accepts both:This allows NuGet to resolve either 2.x or 3.x based on what the consumer has in their project. Our code compiles against the 2.x API surface which is a subset of 3.x.
Risks:
SUBSCRIBEcommand responses)Mitigation:
[2.12.14, 4.0.0)Option B: Dual packages
Publish two variants of the Core package:
StackExchange.Redis.Extensions.Core→ SE.Redis 2.xStackExchange.Redis.Extensions.Core.v3→ SE.Redis 3.xPros: explicit, no surprises.
Cons: doubles the package matrix (Core × Serializers × Compressors), maintenance burden is high.
Option C: Major version bump
Release StackExchange.Redis.Extensions 13.x targeting SE.Redis 3.x only. Keep 12.x on SE.Redis 2.x for consumers who can't upgrade.
Pros: clean separation, follows semver.
Cons: forces a major version bump for what is essentially a transparent dependency upgrade; requires maintaining two branches.
Recommended next steps
[2.12.14, 4.0.0)and add a CI matrix for both versions