# Upgrade NServiceBus pipeline extensions from Version 7 to 8 This documentation provides information on breaking changes affecting maintainers of pipeline extensions such as pipeline behaviors and message mutators. ## IManageUnitOfWork `IManageUnitOfWork` interface is no longer recommended. The unit of work pattern is more straightforward to implement in a pipeline behavior, where the using keyword and try/catch blocks can be used. [Custom unit of work sample](/samples/pipeline/unit-of-work/index.md) is an example of the recommended approach. ## Message mutators with Dependancy Injection (DI) Message mutators that operate on serialized messages (`IMutateIncomingTransportMessages` and `IMutateOutgoingTransportMessages`) in NServiceBus version 8 represent the message payload as `ReadOnlyMemory` instead of `byte[]`. As a result, the messages are immutable and it is no longer possible to change their content. Instead, a modified copy of the payload must be provided and assigned to the `Body` property of the context. ## Removing a behavior from the pipeline is obsolete The `Remove` method is no longer available in `PipelineSettings`. In order to disable a behavior, [replace the behavior](/nservicebus/pipeline/manipulate-with-behaviors_core_8.md#disable-an-existing-step) with an empty one. ## Pipeline delivery constraints The `TryGetDeliveryConstraint` method on the `NServiceBus.Extensibility.ContextBag` property has been removed. In order to access delivery constraints from within the pipeline, use `NServiceBus.Extensibility.ContextBag.TryGet` instead. ```csharp var extensions = context.Extensions; if (extensions.TryGet(out DiscardIfNotReceivedBefore constraint)) { timeToBeReceived = constraint.MaxTime; } ``` ### Pipeline context types changes Throughout the pipeline, all context types (e.g. context for behaviors, stage connectors, and message mutators) have been updated to use `ReadOnlyMemory` instead of `byte[]`. These are: * MutateIncomingTransportMessageContext * MutateOutgoingTransportMessageContext * ConnectorContextExtensions * IIncomingPhysicalMessageContext * IncomingPhysicalMessageContext * IOutgoingPhysicalMessageContext * OutgoingPhysicalMessageContext * SerializeMessageConnector ## Message body reference valid only in scope of message processing References to message bodies exposed through context types as `ReadOnlyMemory` are valid only for the time of message processing. After the processing finishes, the data may not be assumed valid. If message body value is required after processing finishes it must be copied it while it is still in scope. ### Message Mutators: Updating of message bodies The message mutator API for changing the message body has changed. Instead, of `UpdateMessage(byte[] body)` method `MutateIncomingTransportMessageContext` and `MutateOutgoingTransportMessageContext` expose `Body` property of type `ReadOnlyMemory`. In scenarios, where mutators replace the whole message body switching to pipeline behavior might bring significant performance benefits. With a [pipeline behavior](/nservicebus/pipeline/manipulate-with-behaviors.md) it is possible to reduce allocations via [`ArrayPool`](https://learn.microsoft.com/en-us/dotnet/api/system.buffers.arraypool-1) or packages like [RecyclableMemoryStream](https://github.com/Microsoft/Microsoft.IO.RecyclableMemoryStream).