Compatibility
Dekaf's core package targets net10.0 and netstandard2.0. The extension, serialization, compression, Schema Registry, testing, and tool packages still target net10.0.
The project is open to broader target-framework support when it does not regress the net10.0 performance path. netstandard2.0 support is tracked by #1224 and split into staged child issues so compatibility work can land without weakening the current package.
Current Support
| Area | Status |
|---|---|
Core package (Dekaf) | net10.0, netstandard2.0 |
| Compression packages | net10.0 |
| Serialization packages | net10.0 |
| Schema Registry packages | net10.0 |
| Dependency Injection, Hosting, Health Checks | net10.0 |
| Testing package | net10.0 |
| Tools, benchmarks, stress tests | net10.0 |
The net10.0 target stays the primary optimization target. Protocol serialization, production, and consumption hot paths should continue using modern BCL APIs where they are needed for low allocation and throughput.
netstandard2.0 Goal
The compatibility goal is to let older applications consume Dekaf packages without requiring a second Kafka client package, while preserving the existing net10.0 behavior and performance.
The intended path is staged:
- Define the compatibility plan and blocker categories (#1298).
- Establish a core
netstandard2.0restore/build baseline (#1299). - Replace, guard, or polyfill core
net10.0API blockers (#1300). - Add package and smoke validation for the final supported package set (#1301).
Build Probe
The first compatibility probe forced the core package to compile as netstandard2.0 without editing project files:
dotnet build src/Dekaf/Dekaf.csproj --configuration Release `
-p:TargetFrameworks=netstandard2.0 `
-p:TargetFramework=netstandard2.0
That probe confirmed the work is cross-cutting and should not be shipped as one large PR.
netstandard2.0 Restore Baseline
The #1299 baseline keeps Dekaf defaulting to net10.0, but adds the conditional project structure needed for an explicit netstandard2.0 probe:
System.IO.Pipelines,System.Threading.Channels, andSystem.Text.Jsonpackage references are included only when$(TargetFramework)isnetstandard2.0.- Modern compiler-support shims are included only for
netstandard2.0, includingIsExternalInit, required-member attributes, nullable flow annotation support, andSkipLocalsInitAttribute. - The forced probe now restores successfully and gets past the missing package-reference and required-member compiler-support errors.
Run the current probe with:
dotnet build src/Dekaf/Dekaf.csproj --configuration Release `
-p:TargetFrameworks=netstandard2.0 `
-p:TargetFramework=netstandard2.0
The #1300 pass removes the core compile blocker layer. The forced probe now builds cleanly:
dotnet build src/Dekaf/Dekaf.csproj --configuration Release `
-p:TargetFrameworks=netstandard2.0 `
-p:TargetFramework=netstandard2.0
This pass includes:
- CRC32C hardware intrinsics are guarded so
netstandard2.0uses the existing software CRC path. IReadOnlySet<T>public and internal surfaces are target-aliased toIReadOnlyCollection<T>fornetstandard2.0.System.Threading.Lock,PeriodicTimer, non-genericTaskCompletionSource,Task.WaitAsync,CancellationTokenSource.CancelAsync,ArrayBufferWriter<T>,SequenceReader<T>,Index,Range,HashCode,ValueTask.CompletedTask, and related BCL helpers have conditional compatibility shims.- Span-based compression stream APIs use array-based stream calls on
netstandard2.0. - Generic protocol send/read paths no longer require static abstract interface members for
netstandard2.0;net10.0keeps static interface dispatch through the metadata helper. - TLS authentication uses the older
SslStream.AuthenticateAsClientAsyncoverload onnetstandard2.0. - GSSAPI remains part of the API surface, but using it on
netstandard2.0throwsPlatformNotSupportedExceptionbecauseNegotiateAuthenticationis unavailable there.
The #1301 package pass declares netstandard2.0 support for the core Dekaf package only. CI packs the package with both lib/net10.0/Dekaf.dll and lib/netstandard2.0/Dekaf.dll, then restores a sample netstandard2.0 library from the local .nupkg and runs it through a net10.0 console host.
Blocker Categories
Missing Package References
Several APIs are inbox for net10.0 but require package references or replacement when targeting netstandard2.0:
System.IO.PipelinesSystem.Threading.ChannelsSystem.Text.JsonSystem.Runtime.Intrinsics- hashing and runtime support packages used by core protocol paths
The first build child should add conditional package references only for targets that need them, leaving net10.0 package closure unchanged where possible.
Compiler Support Shims
The codebase uses modern C# features such as init and required. A netstandard2.0 target needs compatibility definitions for compiler support types such as:
System.Runtime.CompilerServices.IsExternalInitSystem.Runtime.CompilerServices.RequiredMemberAttributeSystem.Runtime.CompilerServices.CompilerFeatureRequiredAttributeSystem.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute
These shims should be internal, conditional, and included only for older target frameworks.
net10-only API Usage
Some source paths use APIs that do not exist on netstandard2.0:
- span-based stream overrides such as
Stream.Write(ReadOnlySpan<byte>) System.Threading.LockTask.WaitAsync- modern throw helpers
- selected runtime intrinsics and vectorized helpers
Each replacement needs performance review. The net10.0 hot path should keep modern APIs when conditional compilation can isolate the compatibility path.
Package Matrix
Not every package has to multi-target at the same time. The current sequence is:
Dekaf- shipped asnet10.0andnetstandard2.0- serialization and compression packages that can compile without framework-specific hosting dependencies
- Schema Registry packages
- extensions packages where their
Microsoft.Extensions.*dependencies support the chosen older target Dekaf.Testing
Tools, benchmarks, stress tests, and CI utilities should remain net10.0.
Validation Requirements
Compatibility support is not complete until these checks exist:
dotnet buildfornet10.0remains green.- Packable libraries build for every declared target framework.
- A sample or smoke test references the
netstandard2.0asset from a supported runtime. - Unit tests continue running against
net10.0. - Any compatibility helper has focused tests or compile canaries.
Integration tests should keep using the existing runtime target unless a specific compatibility runtime issue requires a separate run.
Run the package smoke locally after packing:
./scripts/RunNetStandardPackageSmoke.ps1
Non-goals
- Do not lower the runtime target for tools, benchmarks, or stress tests.
- Do not replace high-performance
net10.0code with slower shared code when conditional compilation can keep the fast path. - Do not claim
netstandard2.0support until package restore, build, packaging, and smoke validation are all in place.