We have a multitenant NServiceBus endpoint called ContactProcessor that persists contact information. Each tenant has its own database for storing contact information. The messages that are sent to this endpoint have a TenantName header which is used to resolve the tenant’s connection string.
We have a few high-volume tenants that send a lot of messages to this endpoint and they cause performance to suffer for the low-volume tenants. The high-volume tenants “hog” the queue for this endpoint (MSMQ) and they delay the message processing for the low-volume tenants.
I think I can solve this problem by splitting the ContactProcessor endpoint into separate endpoints for each high-volume tenant. Each high-volume tenant will get its own ContactProcessor and queue (ContactProcessor.Tenant1, ContactProcessor.Tenant2, etc) and the low-volume tenants will continue to share the current ContactProcessor endpoint. I’ll need to override the routing for messages that are sent to the new tenant endpoints. E.g. If the message’s TenantName header is “Tenant 1” and Tenant 1 has its own endpoint then send the message to ContactProcess.Tenant1 instead of the shared ContactProcessor endpoint.
I’m not sure what the best approach is for overriding the routing. I could set the message’s destination via SendOptions inside the source message handlers but this seems a bit laborious. Each source message handler would need to be modified. I could add a shared class that handles the tenant routing. Is there a more elegant way to handle the routing? Perhaps hook into the NServiceBus pipeline?