Release Notes v5.x.x
5.0.0
Silverback 5.0.0 is the most significant update in the library’s history, built on years of user feedback and real-world experience. This release is more than just an upgrade, it’s a complete refactoring that enhances flexibility, performance, and maintainability while laying a strong foundation for future innovations.
Highlights
- An improved configuration API that makes it easier to set up Silverback exactly the way you want, with a more intuitive and consistent syntax. The new fluent API is designed to be more readable and straightforward and to giving you more control over the Kafka and MQTT clients that are used under the hood.
services.AddSilverback()
.WithConnectionToMessageBroker(options => options.AddKafka())
.AddKafkaClients(clients => clients
.WithBootstrapServers("PLAINTEXT://localhost:9092")
.AddProducer(producer => producer
.Produce<MyMessage>(endpoint => endpoint
.ProduceTo("my-topic"))
.Produce<MyMessage2>(endpoint => endpoint
.ProduceTo("my-topic-2")))
.AddConsumer(consumer => consumer
.WithGroupId("consumer1")
.AutoResetOffsetToEarliest()
.Consume<MyMessage3>(endpoint => endpoint
.ConsumeFrom("my-topic-3")
.OnError(policy => policy.Retry(3).ThenSkip()))
.Consume<MyMessage4>(endpoint => endpoint
.ConsumeFrom("my-topic-4")
.EnableBatchProcessing(100, TimeSpan.FromSeconds(5))
.OnError(policy => policy.Skip()))));
- The new WrapAndPublish and WrapAndPublishAsync methods allow you to enrich the message envelope with headers, Kafka keys, and other metadata before publishing it.
publisher.WrapAndPublish(
new MyMessage { Content = "Hello, Silverback!" },
envelope => envelope
.AddHeader("custom-header", "custom-value")
.WithKafkaKey("my-key"));
- WrapAndPublishBatch and WrapAndPublishBatchAsync methods extend the WrapAndPublish functionality to support streaming, mapping, and efficient batching with Kafka.
await publisher.WrapAndPublishBatchAsync(
entities,
entity => new MyMessage { Id = entity.Id },
envelope => envelope
.AddHeader("custom-header", "custom-value")
.WithKafkaKey("my-key"));
- The message bus (
IPublisher) has been improved on many levels- is now registered as transient instead of scoped, allowing you to inject it into singleton services
- IEventPublisher, ICommandPublisher, and IQueryPublisher have been replaced by extension methods on
IPublisher, so you don't need multiple dependencies anymore - supports CancellationToken
- supports ValueTask return types
- more performance and reduced allocations
- Many new features to leverage the power of Kafka and MQTT
- Kafka transactions
- Confluent schema registry support
- Kakfa consumer cooperative sticky partition assignment strategy
- MQTT 5 request-response
- Redesigned and improved storage packages
- native support for PostgreSQL and SQLite (more to come in the future), as well as Entity Framework
- rethought and rewritten outbox
- client-side offset storage for Kafka
In the following sections, you'll find more a more detailed and canonical list of improvements, new features, and breaking changes.
What's New
- Clean up code and increase tests coverage
- Reduce allocations and improve performance in many places (see Performance)
- Register IPublisher as transient instead of scoped to allow injecting it into singleton services
- Add
CancellationTokensupport to the message bus (see Using the Message Bus) - Improve builders for error policies
- Support subscribers returning
ValueTask - Support exponential delay in
RetryErrorPolicy - Add new
AddHeader,WithMessageIdandWithKafkaKeyoverloads inProducerEndpointConfigurationBuilderfor easier and more readable configuration - Introduce typed endpoints registration using
Consume<TMessage>andProduce<TMessage>methods (replacingAddInboundandAddOutbound), making the nested configuration more readable and type-safe (see Producing Messages and Consuming Messages) - Automatically set the typed deserializer according to the message type when using
Consume<TMessage>to configure the endpoint (see Deserializing the Consumed Messages) - Automatically set the typed BinaryMessageDeserializer<TModel> according to the message type when using
Consume<TMessage>to configure the endpoint (see Deserializing the Consumed Messages) - Add full fluent API for Kafka and MQTT configuration (see Producing Messages and Consuming Messages)
- Rewrite storage implementation from scratch and introduce new Silverback.Storage.PostgreSql, Silverback.Storage.Sqlite, Silverback.Storage.EntityFramework and Silverback.Storage.Memory packages (see Storage Integration)
- Refactor transactional outbox adding support for transaction enlistment (even if not using Entity Framework) and improving performance (see Transactional Outbox)
- Improve outbox worker reliability
- Add message filtering in producer configuration (see Producing Messages)
- Improve and simplify tombstone handling (see Producing Tombstone Messages and Consuming Tombstone Messages)
- Add
IInboundEnvelopeextensions to get broker specific metadata such asGetKafkaOffset(),GetKafkaTimestamp(),GetMqttResponseTopic()andGetMqttCorrelationData() - Add
IOutboundEnvelopeextensions to set broker specific metadata such asSetKafkaKey(),SetMqttResponseTopic()andSetMqttCorrelationData() - Add
WrapAndProduceandWrapAndProduceAsyncmethods to IPublisher to allow envelope enrichment (setting headers, kafka key, etc.) and dynamic routing (see Producing Messages) - Add
WrapAndProduceBatchandWrapAndProduceBatchAsyncmethods to IPublisher with the same capabilities ofWrapAndProduceandWrapAndProduceAsync, supporting streaming, mapping, and efficient batching with Kafka (see Producing Messages) - Refactor and improve EntityFrameworkDomainEventsPublisher<TDbContext>
- Improve
ITestingHelperto allow waiting for specific topics to be consumed (see Testing) - Add InboundEnvelopeBuilder<TMessage> and OutboundEnvelopeBuilder<TMessage> to testing packages to help creating test envelopes (see Testing)
- Support Kafka cooperative sticky partition assignment strategy
- Implement transactional client-side offset storage (see Kafka Offset Storage)
- Support Kafka transactions (see Kafka Transactions)
- Add support for Confluent schema registry (Avro, Json, and Protobuf), including mock for in-memory testing
- Add
IgnoreNoMatchingSubscribersErrorsetting to MQTT producer endpoints, to prevent throwing when no subscriber is consuming the produced message - Basic support for MQTT 5 request-response
- Add ConsumerNameFilterAttribute to filter the subscribers by consumer name (replaces KafkaGroupIdFilterAttribute and MqttClientIdFilterAttribute)
- Add new built-in (de-)serializers to support raw
string,Streamandbyte[](see Serializing the Produced Messages and Deserializing the Consumed Messages) - Improve Activity handling for sequences (batch processing, chunking, etc.)
- Upgrade to Confluent.Kafka 2.13.1
- Upgrade to MQTTnet 5.1.0
Breaking Changes
This release includes many breaking changes, as the library underwent a significant refactoring. The following list might be incomplete but should give you an overview of the most important changes:
- Refactored the configuration model and related fluent API, refer to the updated Guides and Samples to see what it looks like in the new version
- Many types, properties, and methods have been renamed or modified to improve readability, consistency, and ergonomics
- Reorganized the configuration namespaces, some extension methods might have been moved to a different namespace, thus requiring a different
using. - Changed the endpoint models and most of the configuration models to records with init-only properties
- Building the endpoints directly is still supported, but the strongly recommended preferred way is to use the fluent API; therefore, from now on the documentation will only show that approach
- Removed all builders interfaces and exposed the actual classes directly (e.g.
ISilverbackBuildertoSilverbackBuilder) AddOutbound/AddInboundmethods have been replaced byAddKafkaClients/AddMqttClientsandProduce/ConsumemethodsBatchSettings,ChunkSettings,SequenceSettings,EncryptionSettings, etc. renamed toBatchConfiguration,ChunkConfiguration,SequenceConfiguration,EncryptionConfiguration, etc.Configuremethod for Kafka clients replaced by configuration methods such asWithBootstrapServers,WithGroupId,WithClientId, etc.IBrokerCallbackandAdd*BrokerCallbackHandlermethods renamed toIBrokerClientCallbackandAdd*BrokerClientCallback- ... (many more changes)
- Split the
IMessageSerializerinterface into IMessageSerializer and IMessageDeserializer - Outbox and all storage-dependent features have been rewritten from scratch, look at the Guides for more details about the new implementation
- Important: the new Entity Framework based outbox works slightly differently than the previous one, and you might need to explicitly begin a transaction
- Exactly once guard has been replaced by the client side offset storage (see Kafka Offset Storage)
- Replaced
IEventPublisher,ICommandPublisher, andIQueryPublisherwith equivalent extension methods on IPublisher (see Using the Message Bus)- Consequently removed the
UseModelconfiguration method
- Consequently removed the
- Removed the whole
IBrokerandIBrokerCollectionconstructs- They are superseded by the
IProducerCollectionandIConsumerCollectioninterfaces, as well as theIBrokerClientCollectionwhich grants access to all underlying broker clients
- They are superseded by the
- Changed some details in IProducer/IConsumer and their implementations
- A lot of methods have been changed to return a
ValueTaskinstead of aTask - Kafka key won't be set to a random
Guidanymore but will benullif not explicitly set - Some changes to the default settings:
- Increased default KafkaConsumerConfiguration.MaxDegreeOfParallelism to 100
- Increased default KafkaConsumerConfiguration.BackpressureLimit to 50
- Changed default NewtonsoftJsonMessageDeserializer<TMessage> typename handling to
TypeNameHandling.Noneto lay on the safe side - By default, the
MqttProducerwill not throw an exception anymore if no subscriber is consuming the produced message (can be configured to log a warning, or throw an exception)
- Several changes have been made to ITestingHelper, IKafkaTestingHelper, and IMqttTestingHelper
- Removed the
AddSubscribersmethods allowing to register subscribers via a base type or interface - ... (many more changes)
Migration Guide
The migration from Silverback 4.x.x to 5.x.x is a significant step and requires some effort. The following list is not exhaustive and might not cover all the breaking changes but should give you a good idea of the basic steps:
- Ensure your application targets .NET 10 as starting with v5 Silverback only supports the latest LTS release
- Upgrade all Silverback.* NuGet packages to 5.x.x
- Some namespace usings will need to be adjusted (e.g.,Silverback.Messaging.Configuration → Silverback.Configuration)
- Migrate the endpoints configuration to the new broker clients configuration (an example of the new fluent API can be found in the Highlights section above)
- Replace usage of
IEventPublisher,ICommandPublisher, andIQueryPublisherwith the related extension methods on the basic IPublisher - If using the outbox, adjust the DbContext / database schema
Deprecation Notice
The support for RabbitMQ has been dropped in this release and the Silverback.Integration.RabbitMQ package has been deprecated. See Deprecation notice: packages to be deprecated in Silverback v5.