Elastic.Channels
0.48.0
Prefix Reserved
dotnet add package Elastic.Channels --version 0.48.0
NuGet\Install-Package Elastic.Channels -Version 0.48.0
<PackageReference Include="Elastic.Channels" Version="0.48.0" />
<PackageVersion Include="Elastic.Channels" Version="0.48.0" />
<PackageReference Include="Elastic.Channels" />
paket add Elastic.Channels --version 0.48.0
#r "nuget: Elastic.Channels, 0.48.0"
#:package Elastic.Channels@0.48.0
#addin nuget:?package=Elastic.Channels&version=0.48.0
#tool nuget:?package=Elastic.Channels&version=0.48.0
Elastic.Channels
A thread-safe, batching ChannelWriter for high-throughput data pipelines.
Most users install Elastic.Ingest.Elasticsearch which pulls this package in as a transitive dependency.
What it provides
- Automatic batching — flushes when the buffer hits a max count, a max age, or a max byte budget (netstandard2.1+/net8+), whichever comes first
- Concurrent export — configurable parallelism for sending batches
- Retry with backoff — configurable retry count and backoff function
- Backpressure — bounded inbound buffer with
BoundedChannelFullModecontrol (drop or wait)
BufferOptions
Each channel exposes a BufferOptions instance that controls buffering behavior:
| Option | Description |
|---|---|
InboundBufferMaxSize |
The maximum number of in flight instances that can be queued in memory. If this threshold is reached, events will be dropped |
OutboundBufferMaxSize |
The number of events a local buffer should reach before sending the events in a single call to Elasticsearch. |
OutboundBufferMaxLifetime |
The maximum age of buffer before its flushed |
OutboundBufferMaxBytes |
Optional byte budget per outbound batch (netstandard2.1+/net8+). When set, a single outbound page is sliced into multiple sub-requests at export time so each stays within the limit (see below). |
ExportMaxConcurrency |
Controls how many concurrent Export operations may occur |
ExportMaxRetries |
The maximum number of retries over Export |
ExportBackOfPeriod |
Func that calculates an appropriate backoff time for a retry |
ExportBufferCallback |
Called once whenever a buffer is flushed, excluding retries |
WaitHandle |
Inject a waithandle that will be signalled after each flush, excluding retries. |
Size-aware batching
Requires netstandard2.1 / net8.0 or later. Not available on netstandard2.0 — the property does not exist on that target, so there is no silent no-op.
When individual events vary significantly in size, a fixed item count can produce batches whose serialized body far exceeds the server's max_coordinating_bytes limit, causing 429 rejections. OutboundBufferMaxBytes adds a byte budget as a third early-flush condition alongside count and lifetime — whichever fires first wins.
var options = new IngestChannelOptions<MyDoc>(transport, context)
{
BufferOptions = new BufferOptions
{
OutboundBufferMaxSize = 1_000,
OutboundBufferMaxBytes = 100 * 1024 * 1024, // 100 MB — well under ES's 200 MB default
}
};
How it works — sub-batch at export time:
When the budget is set, ExportAsync serializes each event once into a local buffer, tracks the running byte total, and cuts a new request when the total would exceed the limit. A single outbound page may become N sub-requests, each bounded by the budget. Each event is serialized exactly once — no double-serialize, no retained intermediate buffers.
page[0..N] → ExportAsync
event[0]: serialize → 98 bytes → sub-batch 1 (98 bytes)
event[1]: serialize → 102 bytes → 98+102=200 > budget? flush, start sub-batch 2
event[2]: serialize → 95 bytes → sub-batch 2 (95 bytes)
…
→ each sub-batch is a separate _bulk HTTP request
→ responses merged in page order → single BulkResponse to base retry loop
Oversized individual events (a single event larger than the budget alone) are emitted in their own sub-request. The ItemExceedsBytesBudgetCallback fires as a warning:
var options = new IngestChannelOptions<MyDoc>(transport, context)
{
BufferOptions = new BufferOptions { OutboundBufferMaxBytes = 100 * 1024 * 1024 },
ItemExceedsBytesBudgetCallback = (doc, bytes) =>
logger.LogWarning("Document {Id} is {Bytes:N0} bytes, exceeds batch budget", doc.Id, bytes),
};
Memory: during export, each concurrent export task holds at most OutboundBufferMaxBytes of serialized bytes in a local MemoryStream. Peak = MaxConcurrency × OutboundBufferMaxBytes. The bytes are freed when the export call returns.
When OutboundBufferMaxBytes is null (default): the streaming export path is used unchanged — no sub-batching, no extra memory, identical behaviour to previous releases.
Documentation
Full documentation: https://elastic.github.io/elastic-ingest-dotnet/
- Architecture — how the two-stage buffered pipeline works
- Channels — buffer tuning, callbacks, serialization
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Buffers (>= 4.6.1)
- System.Threading.Channels (>= 10.0.0)
-
.NETStandard 2.1
- System.Threading.Channels (>= 10.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Elastic.Channels:
| Package | Downloads |
|---|---|
|
Elastic.Ingest.Transport
Provides components to build a buffer-backed channel for publishing events to distributed systems over HTTP through Elastic.Transport |
|
|
Raycynix.Extensions.Logging.Elastic
Elasticsearch sink integration for Raycynix Serilog-based logging. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.48.0 | 507 | 6/3/2026 |
| 0.47.0 | 199 | 6/3/2026 |
| 0.46.0 | 366 | 6/2/2026 |
| 0.45.0 | 3,178 | 5/12/2026 |
| 0.44.1 | 593 | 5/12/2026 |
| 0.44.0 | 265 | 5/11/2026 |
| 0.43.0 | 1,377 | 4/20/2026 |
| 0.42.0 | 404 | 4/20/2026 |
| 0.41.2 | 16,916 | 4/15/2026 |
| 0.41.1 | 583 | 4/15/2026 |
| 0.41.0 | 1,388 | 3/31/2026 |
| 0.40.0 | 3,873 | 3/21/2026 |
| 0.39.0 | 476 | 3/20/2026 |
| 0.38.0 | 487 | 3/20/2026 |
| 0.37.0 | 1,799 | 3/5/2026 |
| 0.36.0 | 427 | 3/5/2026 |
| 0.35.0 | 475 | 3/5/2026 |
| 0.34.5 | 8,818 | 3/3/2026 |
| 0.34.4 | 461 | 3/3/2026 |
| 0.34.3 | 485 | 3/3/2026 |