Skip to main content

Provides components to build a buffer-backed channel that flushes batches of data in a controlled (Max N || Max Duration) manner.

Total Downloads
13.0M
13,049,068
Published
Oct 6, 2026
27d ago

Get Started

dotnet add package Elastic.Channels --version 0.53.0
ProductVersions
.NET Standard
netstandard2.0netstandard2.1

README

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 BoundedChannelFullMode control (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

Downloads by Version

Similar & Alternative Packages

Hand-picked matching NuGet libraries based on tags & ecosystem

Depended On By

Find packages that declare this package as a dependency. NuGet does not provide a reverse-dependency endpoint, so candidates are checked on demand.

Adoption Assessment

A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.

Compatibility metadata lists 2 target frameworks; confirm the exact target used by your application.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.