Quickstart
This guide gets you from an empty folder to an application producing and consuming messages through Apache Kafka in a few minutes.
Prerequisites
- The .NET 10 SDK
- Docker to run a local Kafka broker
Start a single-node Kafka broker listening on localhost:9092:
docker run -d --name kafka -p 9092:9092 apache/kafka:4.1.0
Create the Project
Create a new worker service and add the Silverback Kafka integration package:
dotnet new worker -n SilverbackQuickstart
cd SilverbackQuickstart
dotnet add package Silverback.Integration.Kafka
Define the Message
Messages are plain classes: no base class or interface is required.
public class OrderCreatedEvent
{
public int OrderId { get; set; }
}
Configure Silverback
Replace the content of Program.cs with the following configuration: a producer publishing OrderCreatedEvent to the orders topic, a consumer reading from the same topic, and a subscriber handling the consumed messages.
using Silverback.Configuration;
using Silverback.Messaging.Configuration;
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddSilverback()
.WithConnectionToMessageBroker(options => options.AddKafka())
.AddKafkaClients(clients => clients
.WithBootstrapServers("PLAINTEXT://localhost:9092")
.AddProducer(producer => producer
.Produce<OrderCreatedEvent>(endpoint => endpoint
.ProduceTo("orders")))
.AddConsumer(consumer => consumer
.WithGroupId("quickstart")
.AutoResetOffsetToEarliest()
.Consume<OrderCreatedEvent>(endpoint => endpoint
.ConsumeFrom("orders"))))
.AddSingletonSubscriber<OrderCreatedEventHandler>();
builder.Services.AddHostedService<Worker>();
builder.Build().Run();
Produce the Messages
Inject the IPublisher and publish the messages. Silverback routes them to the orders topic according to the producer configuration. Replace the generated Worker.cs with:
using Silverback.Messaging.Publishing;
public class Worker : BackgroundService
{
private readonly IPublisher _publisher;
public Worker(IPublisher publisher)
{
_publisher = publisher;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
int orderId = 0;
while (!stoppingToken.IsCancellationRequested)
{
await _publisher.PublishAsync(new OrderCreatedEvent { OrderId = ++orderId }, stoppingToken);
await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
}
}
}
Consume the Messages
The consumed messages are published to the internal message bus and forwarded to the matching subscribers. A subscriber is just a class with a public method accepting the message.
public class OrderCreatedEventHandler
{
private readonly ILogger<OrderCreatedEventHandler> _logger;
public OrderCreatedEventHandler(ILogger<OrderCreatedEventHandler> logger)
{
_logger = logger;
}
public void Handle(OrderCreatedEvent message) =>
_logger.LogInformation("Order {OrderId} created", message.OrderId);
}
Run It
dotnet run
The log shows the orders being consumed, one per second. Stop the application with Ctrl+C: Silverback disconnects the clients gracefully.
Tip
Producer and consumer usually live in different services. Splitting this example in two applications only requires moving the AddProducer and AddConsumer blocks to the respective service.
Next Steps
- Setting Up Silverback – the available packages and the registration options.
- Using the Message Bus – the in-memory message bus, subscribers and behaviors.
- Producing Messages and Consuming Messages – the producer and consumer configuration in depth.
- Error Handling Policies – what happens when the processing fails.
- Transactional Outbox – produce reliably as part of your database transaction.
- Testing – test your application with the in-memory brokers.
- Samples – more complete examples.