Apache Kafka Implementation in .NET – A Practical Microservices Guide

Modern enterprise applications demand high throughput, fault tolerance, and real-time data processing. Traditional synchronous APIs struggle at scale. This is where Apache Kafka becomes a backbone for event-driven microservices.

In this article, we will explore Kafka implementation using .NET with real-world architecture, producer & consumer examples, and best practices.


Why Kafka for Microservices?

  • High-throughput event streaming
  • Loose coupling between services
  • Fault tolerance and durability
  • Replayable event history
  • Horizontal scalability

Kafka Architecture – Core Concepts

Kafka Components

  • Producer – Publishes events
  • Topic – Logical event stream
  • Partition – Parallelism unit
  • Broker – Kafka server
  • Consumer Group – Scalable consumers
  • Offset – Message position

Kafka Microservices Architecture

+-------------------+
|  Web / API Layer  |
+-------------------+
          |
          v
+-------------------+
| Kafka Producer    |
| (.NET Service)    |
+-------------------+
          |
          v
=================================
|        Kafka Cluster           |
|  Topic: meter-reading-events  |
|  Partitions: 0 | 1 | 2        |
=================================
          |
          v
+-------------------+
| Kafka Consumers   |
| (.NET Workers)   |
+-------------------+
          |
          v
+-------------------+
| DB / Cache / DWH  |
+-------------------+

This architecture enables asynchronous processing, better fault tolerance, and independent service scaling.


Kafka Client for .NET

The official Kafka client for .NET:

Confluent.Kafka

Install Package

dotnet add package Confluent.Kafka

Kafka Producer Implementation (.NET)

Producer Configuration

var config = new ProducerConfig
{
    BootstrapServers = "localhost:9092",
    Acks = Acks.All,
    EnableIdempotence = true
};

Producer Code

public class KafkaProducer
{
    private readonly IProducer<string, string> _producer;

    public KafkaProducer()
    {
        var config = new ProducerConfig
        {
            BootstrapServers = "localhost:9092"
        };

        _producer = new ProducerBuilder<string, string>(config).Build();
    }

    public async Task PublishAsync<T>(string topic, string key, T message)
    {
        var json = JsonSerializer.Serialize(message);

        await _producer.ProduceAsync(topic, new Message<string, string>
        {
            Key = key,
            Value = json
        });
    }
}

Kafka Consumer Implementation (.NET)

Consumer Configuration

var config = new ConsumerConfig
{
    BootstrapServers = "localhost:9092",
    GroupId = "meter-reading-group",
    AutoOffsetReset = AutoOffsetReset.Earliest,
    EnableAutoCommit = false
};

Consumer Code

public class KafkaConsumer
{
    public void Start()
    {
        var config = new ConsumerConfig
        {
            BootstrapServers = "localhost:9092",
            GroupId = "meter-reading-group",
            AutoOffsetReset = AutoOffsetReset.Earliest,
            EnableAutoCommit = false
        };

        using var consumer =
            new ConsumerBuilder<string, string>(config).Build();

        consumer.Subscribe("meter-reading-events");

        while (true)
        {
            var result = consumer.Consume();

            try
            {
                var data = JsonSerializer.Deserialize<MeterReading>(
                    result.Message.Value);

                Process(data);

                consumer.Commit(result);
            }
            catch (Exception)
            {
                // retry / dead-letter handling
            }
        }
    }
}

Offset Management Strategy

Auto-commit is NOT recommended for production systems. Manual offset commits ensure safe processing.

consumer.Commit(result);

Error Handling & Dead Letter Topic (DLT)

Main Topic: meter-reading-events
        |
        v
Consumer Processing
        |
        |-- Success --> Commit Offset
        |
        |-- Failure --> Retry --> DLT
                          |
                          v
             meter-reading-events-dlt

Kafka vs Azure Service Bus

Feature Kafka Azure Service Bus
Throughput Very High Medium
Replay Events Yes Limited
Event Streaming Yes No
Best Use Event-driven systems Commands & workflows

Kafka Best Practices in .NET

  • Use key-based partitioning
  • Enable idempotent producers
  • Manual offset commits
  • Monitor consumer lag
  • Separate topics by domain

When NOT to Use Kafka

  • Simple CRUD applications
  • Low traffic systems
  • Strong transactional consistency required

Conclusion

Kafka with .NET enables scalable, resilient, and event-driven architectures. When designed correctly, it significantly improves system performance and reliability.

However, Kafka demands discipline, monitoring, and architectural maturity.


Comments

Popular posts from this blog

How I Solved a Real Entity Framework Deadlock Caused by Different Table Order in High-Transaction Systems

How I Built a JWT Refresh Token Middleware in ASP.NET Core

Azure Service Bus vs Apache Kafka in .NET Microservices

A Practical Comparison Guide