Multitenancy
In Quick Start we covered how to configure the Web API in single-tenant mode. In that mode, the API works
with one tenant whose identifier is WorkflowApiConstants.SingleTenantId.
For most scenarios, this is sufficient to run Workflow Engine, and you don’t need to think about tenants or other multi-tenant details. Single-tenant mode simply hides those details from you.
Configuration
In the Web API, a tenant is represented by a combination of TenantId, WorkflowRuntime, and a database provider.
A single database provider can serve multiple WorkflowRuntime instances, and each runtime can handle
requests from multiple tenants.
Tenants that differ only by TenantId but are served by the same WorkflowRuntime are called logical tenants.
Tenants that are served by different WorkflowRuntime instances are called physical tenants.
To enable multi-tenant mode, use AddWorkflowTenants instead of AddWorkflowRuntime.
Provide a list of options that describe the physical tenants to create. For example:
builder.Services.AddWorkflowTenants(
new WorkflowTenantCreationOptions
{
// First physical tenant creation options.
TenantIds = ["MsSqlTenant1", "MsSqlTenant2"],
PersistenceProviderId = PersistenceProviderId.Mssql,
ConnectionString = "Server=localhost,1433;Database=master;User Id=SA;Password=MyPassword;"
},
new WorkflowTenantCreationOptions
{
// Second physical tenant creation options.
TenantIds = ["PostgresTenant1", "PostgresTenant2"],
PersistenceProviderId = PersistenceProviderId.Postgres,
ConnectionString = "Host=localhost;Port=5432;Database=postgres;User Id=postgres;Password=MyPassword;"
}
);
// Don't forget to register the database providers you use.
builder.Services.AddWorkflowApiMssql();
builder.Services.AddWorkflowApiPostgres();
This example defines two physical tenants. The first serves the logical tenants MsSqlTenant1 and MsSqlTenant2 using
the Microsoft SQL Server provider, and the second serves PostgresTenant1 and PostgresTenant2 using the PostgreSQL provider.
Key options in WorkflowTenantCreationOptions:
TenantIds— the list of logical tenant identifiers that will be handled by thisWorkflowRuntimeand database provider (i.e., by this physical tenant).PersistenceProviderId— the identifier of the database provider factory used to create bothIWorkflowProviderandIDataProvider. If omitted, the first registered provider will be used. The selected provider must be registered as a service. Available IDs are defined in thePersistenceProviderIdclass.ConnectionString— the database connection string used to create providers. You can define multiple physical tenants that use the same provider factory but different connection strings.
The remaining options in WorkflowTenantCreationOptions let you fine-tune how WorkflowRuntime and providers are created.
Usage
When calling the API in multi-tenant mode, you can explicitly specify TenantId via the
WorkflowApiConstants.TenantIdHeader request header ("Workflow-Api-Tenant-ID"). If the header is missing,
DefaultTenantId is used, which by default is WorkflowApiConstants.SingleTenantId.
In multi-tenant mode, it is recommended to set DefaultTenantId to null. This ensures that every API request must
explicitly provide a TenantId; otherwise, the request is rejected with an error.
When a TenantId is provided, the Workflow API resolves the physical tenant that serves the given logical tenant. The
request is then processed by the corresponding WorkflowRuntime and database provider.
Using the ASP.NET service provider, you can access all tenants via the IWorkflowTenantRegistry service. If you are in
the context of an HTTP request, you can retrieve the current tenant with
IWorkflowTenantRegistry.GetHttpContextWorkflowTenant or via an extension method on IServiceProvider.
public class MyController : ControllerBase
{
private readonly IWorkflowTenantRegistry _tenantRegistry;
public MyController(IWorkflowTenantRegistry tenantRegistry)
{
_tenantRegistry = tenantRegistry;
}
[HttpGet("my-endpoint")]
public IActionResult MyEndpoint()
{
var currentTenant = _tenantRegistry.GetHttpContextWorkflowTenant();
WorkflowRuntime runtime = currentTenant.WorkflowRuntime;
// Use currentTenant here...
return Ok();
}
}