V10 Migration Guide

Overview

Brighter V10 introduces significant improvements and new features while maintaining a clear migration path from V9. This guide provides step-by-step instructions for upgrading your application to V10, addressing breaking changes, and adopting new features.

Key Changes in V10:

  • Cloud Events support

  • OpenTelemetry Semantic Conventions

  • Default Message Mappers

  • Dynamic Message Deserialization

  • Nullable Reference Types (breaking)

  • Simplified Configuration (breaking)

  • Reactor and Proactor terminology (breaking)

  • Polly Resilience Pipeline v8 (breaking)

  • Request Context enhancements

  • InMemory options for testing

  • Transport improvements (PostgreSQL, RabbitMQ, Kafka, AWS)

  • Request ID is now an Id type

Migration Effort: Most applications can be migrated in 1-4 hours, depending on complexity.

Before You Start

Prerequisites

  1. Backup your code: Commit all changes to version control

  2. Review the release notes: Read Release Notes for V10

  3. Update test suite: Ensure your tests are passing on V9

  4. Check dependencies: Review third-party package compatibility

  1. Upgrade in a feature branch: Don't upgrade directly in main/master

  2. Address breaking changes first: Fix compilation errors before adopting new features

  3. Test thoroughly: Run your full test suite after each step

  4. Deploy to staging: Validate in a non-production environment

  5. Monitor production: Watch for issues after deployment

Step 1: Update Package References

Update NuGet Packages

Update all Brighter packages to V10:

Check for Package Conflicts

Step 2: Address Breaking Changes

1. Nullable Reference Types

Breaking Change: Nullable reference types are now enabled across all Brighter projects.

Migration Steps:

  1. Enable nullable reference types in your project (if not already enabled):

  1. Address compiler warnings in Commands, Events, and Handlers:

Before (V9):

After (V10):

  1. Update Message Mappers to handle nullable warnings:

See also: Nullable Reference Types Documentation

2. Simplified Configuration

Breaking Change: Builder methods renamed for clarity.

Before (V9):

After (V10):

Migration Steps:

  1. Replace UseExternalBus with AddProducers

  2. Replace AddServiceActivator with AddConsumers

  3. Update property names: ProducerRegistry instead of passing directly

3. Reactor and Proactor Terminology

Breaking Change: The runAsync flag on Subscription has been renamed to MessagePumpType.

Before (V9):

After (V10):

Migration Table:

V9 Parameter
V10 Parameter
Description

runAsync: false

messagePumpType: MessagePumpType.Reactor

Synchronous, blocking I/O

runAsync: true

messagePumpType: MessagePumpType.Proactor

Asynchronous, non-blocking I/O

See also: Reactor and Proactor Documentation

4. Polly Resilience Pipeline

Breaking Change: TimeoutPolicyAttribute is obsolete. Use UseResiliencePipeline attribute.

Before (V9):

After (V10):

  1. Define a Resilience Pipeline:

  1. Use the new attribute:

  1. Register the pipeline with Brighter:

See also: Policy Retry and Circuit Breaker Documentation

5. Request Context Interface Changes

Breaking Change: IRequestContext interface has new properties.

New Properties:

  • PartitionKey: Set message partition keys dynamically

  • CustomHeaders: Add custom headers via request context

  • ResilienceContext: Integration with Polly resilience pipeline

  • OriginatingMessage: Access the original message (for consumers)

Migration: Most code should not be affected unless you implement IRequestContext directly.

If you implement IRequestContext (rare):

Using new properties:

6. Request Id and CorrelationId type change

In V9 the Request type used a Guid to represent the identity of a Command or Event. In V10, as part of a move away from primitives, we have changed this to be a type Id. An Id can be constructed from a string using its ToString() method. If you have used a Guid then you will need to turn the Guid into a string.

Within IRequest both Id and CorrelationId both use the type Id in V10.

If you were using a Guid to create a random identity, you can just use Id.Random() instead which has the same behavior.

Before:

After:

Step 3: Adopt New Features (Optional)

1. Cloud Events Support

V10 adds full Cloud Events specification support.

Benefits:

  • Standardized event metadata

  • Better interoperability with other systems

  • Rich event context information

Adoption Steps:

  1. Update Publication to include Cloud Events properties:

  1. Use Cloud Events headers in your mapper (optional):

See also: Cloud Events Documentation

2. Default Message Mappers

V10 allows you to omit message mappers for simple JSON serialization.

Benefits:

  • Less boilerplate code

  • Faster development

  • Still supports custom mappers for complex scenarios

Before (V9) - Required Mapper:

After (V10) - No Mapper Needed:

When to use custom mappers:

  • Complex transformations

  • Non-JSON formats (XML, Protobuf, etc.)

  • Transform pipelines (encryption, compression, claim check)

  • Custom header mapping

See also: Message Mappers Documentation

3. Dynamic Message Deserialization

V10 supports multiple message types on the same channel.

Benefits:

  • Content-based routing

  • Flexible message processing

  • Better use of infrastructure

Example:

See also: Dynamic Deserialization Documentation

4. OpenTelemetry Semantic Conventions

V10 adopts OpenTelemetry Semantic Conventions for messaging.

Impact: Trace spans will have different names and attributes than V9.

Benefits:

  • Standard messaging conventions

  • Better integration with APM tools

  • Consistent telemetry across systems

Migration:

  1. Update dashboards and alerts to use new span names

  2. Review trace queries for compatibility

  3. Test observability in staging environment

V9 Span Names:

  • Paramore.Brighter.CommandProcessor.Send

  • Paramore.Brighter.MessagePump.Receive

V10 Span Names (OTel Semantic Conventions):

  • messaging.send

  • messaging.receive

  • messaging.process

See also: Telemetry Documentation

5. InMemory Options for Testing

V10 provides comprehensive InMemory implementations for testing.

Benefits:

  • Fast test execution

  • No external dependencies

  • Easy CI/CD integration

Example:

See also: InMemory Options Documentation

Step 4: Test Your Migration

Unit Tests

  1. Run existing unit tests:

  1. Address test failures:

    • Update mocks for IRequestContext new properties

    • Update assertions for OpenTelemetry span names

    • Fix nullable reference warnings

Integration Tests

  1. Test with InMemory components (fast):

  1. Test with real transports (slower, more complete):

Performance Testing

Compare V9 and V10 performance:

Expected: V10 should have similar or better performance due to optimizations.

Step 5: Deploy to Staging

Pre-Deployment Checklist

Deployment Steps

  1. Deploy to staging environment

  2. Run smoke tests

  3. Monitor metrics:

    • Message processing latency

    • Error rates

    • Resource usage (CPU, memory)

  4. Check logs for warnings or errors

  5. Validate telemetry (traces, metrics)

Monitoring

Watch for:

  • Increased error rates

  • Performance degradation

  • OpenTelemetry trace issues

  • Null reference exceptions

Step 6: Deploy to Production

Production Deployment

  1. Deploy during low-traffic period

  2. Use blue-green or canary deployment if possible

  3. Monitor closely for first 24 hours

  4. Have rollback plan ready

Post-Deployment

  • Review logs for issues

  • Check application metrics

  • Validate message processing

  • Monitor OpenTelemetry traces

Common Migration Issues

Issue 1: Nullable Reference Warnings

Symptom: CS8618, CS8600, CS8602 warnings

Solution: See Nullable Reference Types Documentation

Issue 2: Method Not Found

Symptom: UseExternalBus method not found

Solution: Replace with AddProducers

Issue 3: Property Not Found on Subscription

Symptom: runAsync property does not exist

Solution: Use messagePumpType: MessagePumpType.Proactor or MessagePumpType.Reactor

Issue 4: TimeoutPolicy Not Working

Symptom: TimeoutPolicyAttribute marked as obsolete

Solution: Migrate to UseResiliencePipeline with Polly v8

Issue 5: Telemetry Spans Changed

Symptom: Dashboard queries not finding spans

Solution: Update queries to use OpenTelemetry Semantic Convention names

Rollback Plan

If you need to roll back to V9:

  1. Revert package versions:

  1. Revert code changes:

  1. Redeploy V9 version

  2. Investigate issues before attempting V10 migration again

Getting Help

Resources

Reporting Issues

If you encounter issues during migration:

  1. Check existing issues: Search GitHub Issues

  2. Create a new issue with:

    • V9 and V10 versions

    • Minimal reproduction example

    • Error messages and stack traces

    • Environment details (.NET version, OS, transport)

Summary

Migrating to Brighter V10 involves:

  1. Update packages to V10

  2. Address breaking changes:

    • Nullable reference types

    • Simplified configuration API

    • Reactor/Proactor terminology

    • Polly Resilience Pipeline

  3. Adopt new features (optional):

    • Cloud Events

    • Default message mappers

    • Dynamic deserialization

    • OpenTelemetry conventions

    • InMemory testing options

  4. Test thoroughly

  5. Deploy to staging, then production

  6. Monitor and address any issues

Most migrations can be completed in 1-4 hours. The breaking changes are straightforward, and V10 provides significant improvements in features, performance, and developer experience.

Good luck with your migration! 🚀

Last updated

Was this helpful?