[FEAT] Multitenancy
We currently use a TenantId in all our tables, so that data from multiple tenants can be stored in one database instance.
Are there any plans to support Multitenancy in the persistance layer?
I do want support for multitenant applications, including the workflow server. Let's update the models with a string? TenantId property and update the persistence providers.
Things to do:
WorkflowDefinition
Up until now, there was no need for a WorkflowDefinition model - the WorkflowDefinitionVersion model was sufficient, since all of the properties were versioned anyway.
However, we need to add a TenantId property, which itself is not versioned. Although we could technically add it to WorkflowDefinitionVersion, let's not; instead, let's introduce WorkflowDefinition which would look as follows:
public class WorkflowDefinition
{
public string Id { get; set; }
public string? TenantId { get; set; }
public Instant CreatedAt { get; set; }
}
The WorkflowDefinitionVersion model already contains a DefinitionId property that represents the logical workflow definition ID, so that's fine.
IWorkflowDefinitionStore
The IWorkflowDefinitionStore needs to be refactor-renamed to IWorkflowDefinitionVersionStore, including all of its current implementations.
Then, a new interface needs to be created called IWorkflowDefinitionStore that can read and write WorkflowDefinition objects to the underlying persistence layers.
When listing all workflow definitions, the method should accept an optional TenantId value. IF specified, the underlying persistence provider should use this value as a WHERE clause to make sure that only workflow definitions belonging to the specified tenant are returned.
WorkflowInstance
The WorkflowInstance model probably does not need to be updated, since a WorkflowInstance has a DefinitionId, which points to a WorkflowDefinition, which has a TenantId.
What's the status of this? Is this in the roadmap or in-view for now?
Some initial exploratory work has been done, but it's far from complete. It's likely to get more attention later this year, after the Elsa 2 release.
Hi @sfmskywalker
You've probably already thought of this but I'm just thinking about the multi-tenancy and the implications for activity configuration.
An example might be that a tenant has their own email service, blob storage, telnyx provider etc. So if a tenant wants to use these activities there would need to be a way of them setting their own configuration.
In the same way, maybe this is a good opportunity for splitting out things like activities that need some kind of auth token, like a token from a OAuth flow, e.g. you have a Slack post activity, but need to authorise your ELSA app through the slack app auth flow and storing that access token for that tenant.
Do you see this as a developer implemented feature or part of ELSA?
Cheers Chris
Hi Chris,
I have indeed put some thought into this, but not nearly enough.
The way I see it there are basically 2 degrees of multi-tenancy (there are more, depending on how coarse you define them):
- Database Table multi-tenancy: each row has a "TenantId" column.
- Application multi-tenancy: each tenant has its own database, schema or prefixed set of tables in same database.
Database Table
If we want to support Database Table multi-tenancy, then that requires work on Elsa's side of things, since this touches pretty much everything.
Application
To support Application multi-tenancy, we don't need to change anything in Elsa - the developer can choose any multi-tenancy package they want or build it themselves. For example, Orchard Core creates a copy of the Service Collection object for each tenant defined in the system.
This also allows each tenant to have its own set of registered services, such as its own email service, blob storage, telnyx provider, etc.
Do you see this as a developer implemented feature or part of ELSA?
This depends on the degree of multi-tenancy you're after, but it sounds like you'd be interested in Application-level multi-tenancy.
A quick google-search results in quite a few articles about implementing it yourself. I forgot its name, but I also know there's a general-purpose .NET library out there that does a lot of the work for you already.
All that being said, I would not be opposed to creating an "Elsa.Multitenancy" package that does the same (or similar) thing Orchard Core does.
am dealing with a business problem where multiple tenants can use the same set of workflows, but the workflows need to be made available to a tenant based on some feature flag
https://github.com/elsa-workflows/elsa-core/discussions/4479
I've outlined three distinct levels:
- Level 1: Support for a TenantId field on Elsa's domain entities. This allows a customer to have its own multi-tenant setup.
- Level 2: The ability to use one database for multiple tenants, with each tenant having its unique schema or table name prefix, akin to OC's approach.
- Level 3: Just like OC, we're considering a service container for each tenant, referred to as a "shell" in OC. This provides maximum flexibility for data, configuration, and available features for each tenant. Additionally, shells enable users to deploy new configurations and features in real-time without restarting the application container — essential for cloud hosting to prevent disruptions.
So good to see progress here! 🥳
In my case I'm at Level 3, I have a mix multiple tenants in multiple DBs.
A bit painfull but... what can I say.
Anyway, looking forward!
Looking forward to this as well 👍
Hey - just checking if you think this is still going to be in the 3.2 release? If so I'm happy to wait a few weeks, otherwise I'll need to consider rolling my own solution
That’s still the plan.