Skip to content

Multi-Tenancy with Wolverine

Wolverine has first class support for multi-tenancy by tracking the tenant id as message metadata. When invoking a message inline, you can execute that message for a specific tenant with this syntax:

cs
public static async Task invoking_by_tenant(IMessageBus bus)
{
    // Invoke inline
    await bus.InvokeForTenantAsync("tenant1", new CreateTodo("Release Wolverine 1.0"));

    // Invoke with an expected result (request/response)
    var created =
        await bus.InvokeForTenantAsync<TodoCreated>("tenant2", new CreateTodo("Update the Documentation"));
}

snippet source | anchor

When using this syntax, any cascaded messages will also be tagged with the same tenant id. This functionality is valid with both messages executed locally and messages that are executed remotely depending on the routing rules for that particular message.

To publish a message for a particular tenant id and ultimately pass the tenant id on to the message handler, use the DeliveryOptions approach:

cs
public static async Task publish_by_tenant(IMessageBus bus)
{
    await bus.PublishAsync(new CreateTodo("Fix that last broken test"),
        new DeliveryOptions { TenantId = "tenant3" });
}

snippet source | anchor

Cascading Messages

As a convenience, you can embed tenant id information into outgoing cascading messages with these helpers:

cs
public static IEnumerable<object> Handle(IncomingMessage message)
{
    yield return new Message1().WithTenantId("one");
    yield return new Message2().WithTenantId("one");

    yield return new Message3().WithDeliveryOptions(new DeliveryOptions
    {
        ScheduleDelay = 5.Minutes(),
        TenantId = "two"
    });
    
    // Long hand
    yield return new Message4().WithDeliveryOptions(new DeliveryOptions
    {
        TenantId = "one"
    });

snippet source | anchor

Released under the MIT License.