Skip to main content

Consumer Options

Complete reference for all consumer configuration options.

These methods are available anywhere a ConsumerBuilder<TKey,TValue> is used, including dependency injection registration:

// Before: DI examples only showed connection and group settings.
builder.Services.AddDekaf(dekaf =>
{
dekaf.AddConsumer<string, string>(consumer => consumer
.WithBootstrapServers("localhost:9092")
.WithGroupId("orders"));
});

// After: DI uses the full consumer builder.
builder.Services.AddDekaf(dekaf =>
{
dekaf.AddConsumer<string, string>(consumer => consumer
.WithBootstrapServers("localhost:9092")
.WithGroupId("orders")
.WithFetchMinBytes(1024)
.WithFetchMaxBytes(50 * 1024 * 1024)
.WithPrefetchPipelineDepth(4)
.WithSaslScramSha512("user", "password")
.SubscribeTo("orders"));
});

Configuration Binding

Dekaf.Extensions.DependencyInjection can bind consumer settings from an IConfiguration section. Keys use ConsumerOptions property names:

{
"Kafka": {
"Consumers": {
"Orders": {
"BootstrapServers": [
"broker1:9092",
"broker2:9092"
],
"ClientId": "orders-consumer",
"GroupId": "orders",
"AutoOffsetReset": "Earliest",
"OffsetCommitMode": "Manual",
"FetchMinBytes": 1024,
"FetchMaxBytes": 52428800,
"FetchBufferMemoryBytes": 104857600,
"FetchMaxWaitMs": 200,
"MaxPollRecords": 500,
"UseTls": true
}
}
}
}
builder.Services.AddDekaf(dekaf =>
{
dekaf.AddConsumer<string, Order>(
builder.Configuration.GetSection("Kafka:Consumers:Orders"),
consumer => consumer
.WithValueDeserializer(new JsonDeserializer<Order>())
.SubscribeTo("orders"));
});

Configuration is applied before the optional fluent callback, so fluent calls can override values from appsettings.json.

Fluent APIConfig keyNotes
WithBootstrapServers(...)BootstrapServersServer list (prefer params string[] in code; comma-separated string and JSON arrays are also supported)
WithClientId(...)ClientIdString
WithClientDnsLookup(...)ClientDnsLookupUseAllDnsIps or ResolveCanonicalBootstrapServersOnly
WithBootstrapResolveTimeout(...)BootstrapResolveTimeoutMsMilliseconds; default 120000
WithGroupId(...)GroupIdString
WithGroupInstanceId(...)GroupInstanceIdString
WithGroupRemoteAssignor(...)GroupRemoteAssignorCommon values: uniform, range
WithOffsetCommitMode(...)OffsetCommitModeAuto or Manual
WithOffsetStoreTiming(...)OffsetStoreTimingAfterProcessing (default, at-least-once) or OnDelivery (at-most-once)
WithAutoOffsetStore(...)EnableAutoOffsetStoreBoolean; disable for explicit StoreOffset acknowledgment
WithAutoCommitInterval(...)AutoCommitIntervalMsMilliseconds
WithAutoOffsetReset(...)AutoOffsetResetLatest, Earliest, None
WithAutoOffsetResetByDuration(...)AutoOffsetReset, AutoOffsetResetDurationUse AutoOffsetReset: ByDuration plus a duration, or Kafka-style by_duration:PT24H
WithAutoOffsetResetNewPartitions(...)AutoOffsetResetNewPartitionsOptional KIP-1327 policy for newly-expanded partitions; Latest or Earliest
WithAutoOffsetResetNewPartitionsByDuration(...)AutoOffsetResetNewPartitions, AutoOffsetResetNewPartitionsDurationOptional independent duration policy for newly-expanded partitions
WithFetchMinBytes(...)FetchMinBytesBytes
WithFetchMaxBytes(...)FetchMaxBytesBytes
WithFetchBufferMemory(...)FetchBufferMemoryBytesAggregate raw Fetch response bytes; default 100 MiB
WithMaxPartitionFetchBytes(...)MaxPartitionFetchBytesBytes
WithFetchMaxWait(...)FetchMaxWaitMsMilliseconds
WithFetchSessions(...)EnableFetchSessionsBoolean
WithMaxPollRecords(...)MaxPollRecordsInteger
WithSessionTimeout(...)SessionTimeoutMsMilliseconds
WithHeartbeatInterval(...)HeartbeatIntervalMsMilliseconds
WithIsolationLevel(...)IsolationLevelReadUncommitted or ReadCommitted
WithPartitionEof(...)EnablePartitionEofBoolean
WithQueuedMinMessages(...)QueuedMinMessagesInteger
WithQueuedMaxMessagesKbytes(...)QueuedMaxMessagesKbytesKiB; omit to keep auto-tuning
WithPrefetchPipelineDepth(...)PrefetchPipelineDepthInteger
WithConnectionsMaxIdle(...)ConnectionsMaxIdleMsMilliseconds; -1 disables
WithConnectionTimeout(...)ConnectionTimeoutTimeSpan
WithConnectionTimeoutMax(...)ConnectionTimeoutMaxTimeSpan; Kafka socket.connection.setup.timeout.max.ms
WithTcpKeepAlive(...)EnableTcpKeepAlive, TcpKeepAliveTime, TcpKeepAliveInterval, TcpKeepAliveRetryCountSocket keepalive
WithConnectionsPerBroker(...)ConnectionsPerBrokerInteger
WithAdaptiveConnections(...)EnableAdaptiveConnections, MaxConnectionsPerBrokerSet EnableAdaptiveConnections to false to disable
WithAdaptiveFetchSizing(...)EnableAdaptiveFetchSizing, AdaptiveFetchSizingOptionsBind nested adaptive sizing fields
UseTls(...)UseTls, TlsConfigTlsConfig can bind certificate path fields
WithRemoteCertificateValidationCallback(...)Runtime callbackCustom TLS certificate validation
WithSaslPlain(...) / WithSaslScramSha512(...)SaslMechanism, SaslUsername, SaslPasswordSaslMechanism values match the enum names
WithGssapi(...)SaslMechanism, GssapiConfigUse SaslMechanism: Gssapi
WithOAuthBearer(...)SaslMechanism, OAuthBearerConfigUse SaslMechanism: OAuthBearer
WithOAuthBearerJwtBearer(...)Runtime callbackSigns JWT assertions with RSA/ECDSA keys
WithMetadataRecoveryStrategy(...)MetadataRecoveryStrategyNone or Rebootstrap
WithMetadataClusterCheck(...)MetadataClusterCheckEnabledKIP-1242 identity check; default true, ignored with None recovery
WithMetadataRecoveryRebootstrapTrigger(...)MetadataRecoveryRebootstrapTriggerMsMilliseconds

Topics, deserializers, rebalance listeners, interceptors, and retry policies are objects or runtime choices, so configure those in the fluent callback.

Connection Settings

WithBootstrapServers

Kafka broker addresses. Prefer the typed params string[] overload in code; the single-string overload remains a convenience for configuration-style comma-separated values.

.WithBootstrapServers("localhost:9092")
.WithBootstrapServers("broker1:9092", "broker2:9092")
.WithBootstrapServers("broker1:9092,broker2:9092")

WithClientId

Client identifier:

.WithClientId("order-processor")

Consumer Group Settings

WithGroupId

Consumer group identifier (required for group consumption):

.WithGroupId("order-processors")

WithGroupInstanceId

Static membership ID for faster rebalances:

.WithGroupInstanceId("instance-1")

Offset Management

WithOffsetCommitMode

How offsets are committed (matches Kafka's enable.auto.commit):

.WithOffsetCommitMode(OffsetCommitMode.Auto) // Automatic commit in background (default)
.WithOffsetCommitMode(OffsetCommitMode.Manual) // You call CommitAsync() explicitly

Processing Guarantees

Intent-level methods that configure commit mode, offset storage, and staging timing together (see Delivery Semantics):

.WithAtLeastOnceProcessing() // The default, stated explicitly: offsets become committable
// only after the loop demonstrably processed the record
.WithAtMostOnceProcessing() // Confluent-style: offsets committable at delivery,
// before processing runs
.WithAutoOffsetStore(false) // Strict at-least-once: only offsets you pass to
// StoreOffset(...) are ever committed
.WithOffsetStoreTiming(OffsetStoreTiming.AfterProcessing) // Granular knob behind the
// intent methods (AfterProcessing | OnDelivery)

WithAutoCommitInterval

Control how often offsets are committed in Auto mode:

.WithAutoCommitInterval(TimeSpan.FromSeconds(5)) // Same, using TimeSpan

WithAutoOffsetReset

Where to start when no committed offset exists:

.WithAutoOffsetReset(AutoOffsetReset.Latest) // New messages only (default)
.WithAutoOffsetReset(AutoOffsetReset.Earliest) // From beginning
.WithAutoOffsetReset(AutoOffsetReset.None) // Throw exception
.WithAutoOffsetResetByDuration(TimeSpan.FromHours(24))

Configuration can use either a separate duration value:

{
"AutoOffsetReset": "ByDuration",
"AutoOffsetResetDuration": "24:00:00"
}

or Kafka's ISO-8601 form:

{
"AutoOffsetReset": "by_duration:PT24H"
}

For KIP-1327 brokers, newly-expanded partitions can use an independent policy:

.WithAutoOffsetResetNewPartitions(AutoOffsetReset.Earliest)
.WithAutoOffsetResetNewPartitionsByDuration(TimeSpan.FromHours(1))

Use AutoOffsetResetNewPartitions and AutoOffsetResetNewPartitionsDuration for configuration binding. If unset, newly-expanded partitions use the base policy above. Committed offsets still take precedence.

Fetch Settings

WithMaxPollRecords

Maximum messages per poll:

.WithMaxPollRecords(500) // Default: 500

Fetch Tuning

Control how data is fetched from brokers:

.WithFetchMinBytes(1024)
.WithFetchMaxBytes(50 * 1024 * 1024)
.WithFetchBufferMemory(100L * 1024 * 1024)
.WithMaxPartitionFetchBytes(4 * 1024 * 1024)
.WithFetchMaxWait(TimeSpan.FromMilliseconds(200))
.WithFetchSessions(enabled: true)

WithFetchBufferMemory bounds the exact aggregate bytes held by raw Fetch responses across brokers and pipelined requests. It must be at least the configured FetchMaxBytes. An adaptive or oversized first-batch response larger than the limit is admitted only when it is the sole reservation. Coordinator responses do not consume this budget. Observe current pressure through dekaf.consumer.fetch_buffer.used_bytes, free_bytes, depleted_percent, and depleted_duration.

Session Settings

WithSessionTimeout

How long before consumer is considered dead:

.WithSessionTimeout(45000) // 45 seconds (default)
.WithSessionTimeout(TimeSpan.FromSeconds(45)) // Same, using TimeSpan

Subscription

SubscribeTo

Subscribe to topics during build:

.SubscribeTo("orders")
.SubscribeTo("orders", "payments", "notifications")

SubscribeToPattern

Subscribe with a broker-side topic name pattern:

.SubscribeToPattern("orders-.*")

Kafka evaluates the pattern on the broker using RE2/J-compatible syntax. Dekaf sends the pattern as-is; .NET regular expression syntax is not translated.

Server-side pattern subscription requires Kafka 4.1+ brokers with ConsumerGroupHeartbeat v1. Use Subscribe(Func<string, bool>) on IKafkaConsumer when you need arbitrary .NET predicates or compatibility with older brokers. That overload remains client-side and refreshes metadata to find matching topics.

Rebalancing

WithRebalanceListener

Get notified of partition changes. If the listener also implements IPartitionStopListener, OnPartitionsStoppedAsync runs during graceful CloseAsync or DisposeAsync with the current assignment before final auto-commit, LeaveGroup, assignment cleanup, and resource disposal:

.WithRebalanceListener(new MyRebalanceListener())

The same method accepts IConsumerAwareRebalanceListener. Its callbacks receive an IRebalanceConsumer view with safe commit, seek, pause/resume, metadata, and offset operations. The view is invalidated as soon as the callback completes.

The stop callback is best-effort and bounded to five seconds. If it observes shutdown cancellation, Dekaf still completes local cleanup before rethrowing the cancellation from CloseAsync.

Networking

WithConnectionsMaxIdle

Maximum time an unused broker connection stays open before the client closes it:

.WithConnectionsMaxIdle(TimeSpan.FromMinutes(9)) // Default: 540000ms
.WithConnectionsMaxIdle(Timeout.InfiniteTimeSpan) // Disable idle reaping

The default is 9 minutes, slightly below Kafka's broker-side connections.max.idle.ms default of 10 minutes. Connections with in-flight requests are not reaped.

WithConnectionTimeout

Maximum time allowed for socket connection setup, including TLS and SASL handshakes:

.WithConnectionTimeout(TimeSpan.FromSeconds(10))

Set a larger maximum to enable KIP-601 adaptive setup deadlines. Consecutive failures grow the effective timeout exponentially with ±20% jitter, capped at the maximum. A successful setup resets it. Reconnect backoff remains separate.

.WithConnectionTimeout(TimeSpan.FromSeconds(10))
.WithConnectionTimeoutMax(TimeSpan.FromSeconds(127))

When only WithConnectionTimeout is set, the maximum follows the initial value, preserving fixed-timeout behavior. Failure progression follows the broker ID plus advertised host:port. DNS address rotation for that broker and endpoint retains it; a different broker ID or advertised endpoint starts fresh.

WithTcpKeepAlive

Enable, disable, or tune TCP keepalive probes:

.WithTcpKeepAlive(false) // Disable keepalive
.WithTcpKeepAlive(TimeSpan.FromMinutes(2), TimeSpan.FromSeconds(30), retryCount: 3)

Security

UseTls

Enable TLS:

.UseTls()
.UseTls(tlsConfig)
.UseMutualTls(caCert, clientCert, clientKey)

Custom TLS certificate validation can be attached for pinning or private PKI. Setting a callback enables TLS for the connection.

.WithRemoteCertificateValidationCallback((sender, cert, chain, errors) =>
errors == SslPolicyErrors.None)

SASL Authentication

.WithSaslPlain("username", "password")
.WithSaslScramSha256("username", "password")
.WithSaslScramSha512("username", "password")
.WithOAuthBearerJwtBearer(options =>
{
options.TokenEndpoint = "https://auth.example.com/oauth2/token";
options.ClientId = "my-kafka-client";
options.PrivateKey = rsaOrEcdsaPrivateKey;
options.Audience = "kafka";
options.Scopes = ["kafka:consume"];
})

Serialization

WithKeyDeserializer / WithValueDeserializer

Custom deserializers:

.WithKeyDeserializer(new JsonDeserializer<OrderKey>())
.WithValueDeserializer(new JsonDeserializer<Order>())

Advanced Settings

WithPartitionEof

Receive notification when reaching end of partition:

.WithPartitionEof(true)

WithIsolationLevel

For transactional reads:

.WithIsolationLevel(IsolationLevel.ReadCommitted) // Only committed messages
.WithIsolationLevel(IsolationLevel.ReadUncommitted) // All messages (default)

Observability

WithLoggerFactory

.WithLoggerFactory(loggerFactory)

All Options Reference

MethodDefaultDescription
WithBootstrapServers(required)Broker addresses
WithClientId"dekaf-consumer"Client identifier
WithClientDnsLookupUseAllDnsIpsDNS lookup mode
WithBootstrapResolveTimeout120000msInitial bootstrap DNS retry deadline
WithGroupIdnullConsumer group ID
WithGroupInstanceIdnullStatic membership ID
WithOffsetCommitModeAutoOffset management mode
WithOffsetStoreTimingAfterProcessingWhen offsets become committable (at-least-once default)
WithAutoOffsetStoretrueAutomatic offset staging
WithAutoCommitInterval5000msAuto-commit interval
WithAutoOffsetReset, WithAutoOffsetResetByDurationLatestStart position
WithFetchMinBytes1Minimum fetch bytes
WithFetchMaxBytes52428800Maximum total fetch bytes
WithFetchBufferMemory104857600Aggregate queued and in-flight raw Fetch response limit
WithMaxPartitionFetchBytes1048576Maximum fetch bytes per partition
WithFetchMaxWait200msMaximum fetch wait
WithFetchSessionstrueEnable incremental fetch sessions
WithMaxPollRecords500Max messages per poll
WithSessionTimeout45000msSession timeout
WithHeartbeatInterval3000msGroup heartbeat interval
SubscribeTo(none)Topics to subscribe
SubscribeToPattern(none)Broker-side topic regex subscription; Kafka 4.1+
WithRebalanceListenernullRebalance callbacks
WithPartitionEoffalseEOF notifications
WithQueuedMinMessages100000Prefetch target count
WithQueuedMaxMessagesKbytesauto-tunedPrefetch memory limit
WithPrefetchPipelineDepth3Overlapping prefetch operations
WithConnectionsMaxIdle540000msClose unused broker connections; Timeout.InfiniteTimeSpan disables
WithConnectionsPerBroker2TCP connections per broker
WithAdaptiveConnectionsenabled (max 4)Auto-scale connections under load
WithConnectionTimeout30000msSocket connection setup timeout
WithConnectionTimeoutMaxSame as initialMaximum adaptive connection setup timeout
WithTcpKeepAliveenabledTCP keepalive; 2m idle, 30s interval, 3 retries
UseTlsfalseEnable TLS
WithRemoteCertificateValidationCallbacknullCustom TLS certificate validation