Feature flags and NServiceBus

Are there any recommended ways to roll out or control features with feature flags with NServiceBus features or messaging in general? For example, we deploy a Saga today, but we want it to start operating on a specific date in the future. Or, the other way around, we want to retire a Saga at a specific moment. In both cases, doing a deployment at the precise time is not the best option.

I imagine I can come up with solutions, like evaluating the feature flag on the handlers that start the saga and either proceed or discard the message, but I am wondering if someone has experience with it and discovered some gotchas or tricks that I should take into consideration.

Hi Francesc,

When you say you want the saga to start operating on a specific date in the future, do you mean that it should process every message received after that point in time or that you should process every message sent after that point in time. There is no guaranteed order reading messages out of the input queue, and messages can spend time in delayed retries (or in ServiceControl) for some time so you need to be a bit careful about this.

I would not put the logic in the handler/saga unless it is related to the business function. Instead, I would look at implementing a pipeline behavior. Putting a behavior into the IInvokeHandlersContext will allow you to detect when a given handler/saga is about to be invoked, choose to skip it based on the incoming message (i.e. comparing it’s Sent timestamp to your feature trigger timestamp), and log that fact. You can install the feature as needed and remove it once the date has passed.

Here’s a sample to get you started.

Using this approach, the messages will still be routed to the endpoint and the saga instance will be loaded. This means if a message can start a saga, it can still create the instance, even though the handler will not be called. Whether or not that’s an issue will depend on your specific case.

The messages are still handled (even if no handler is called) so they will go to your audit queue.

Regards,
Mike

Every message sent after that point.

Using behaviours does seem a lot cleaner than adding “ifs” inside the handler. On the other hand, it would be possible that a single event was handled by more than one handler and the behaviour would deactivate all of them, which could be unexpected. Maybe I could combine the behaviour with an attribute to decorate the handlers (or saga) passing the feature flag id? Then I could add the behaviour to all endpoints and just apply the attributes where necessary.

That could work. That way you can say “if there’s no attribute, then execute the handler”. It’s safe by default and you can’t accidentally skip a handler.

One thing to be aware of, is that this would have to apply to a class, not a method. The handler context does not contain the details of the handling method, only the class. It only keeps a fuction delegate so that it can call the method.

In your case, you want it to apply to an entire saga, so that will work. Give it a try and let us know how you get on.

Good. That’s in our backlog now. I’ll let you know our feedback once it’s done.

Thanks