The most expensive restart in SaaS is often the one nobody planned: onboarding a new customer. Every SaaS team expects adding a tenant to be a database operation. I still see production systems where it is a deployment.
I am Mike Lukinov, co-founder of Optimajet. In July 2026 we shipped Workflow Engine by Optimajet version 22.0.0, and for SaaS teams it changes the thing that matters most: tenants become runtime objects instead of startup configuration. Tenants register and unregister while the host is running, and multi-tenancy is finally full and hybrid, meaning every layer of engine data can be tenant-scoped or shared, side by side in one installation.
Here is the scene that drove this work. Last month I spoke with a team running about 150 enterprise tenants on .NET. Everything worked, until sales signed one more customer. Their onboarding checklist contained the line "restart production". Every restart window interrupted other tenants' approvals mid-flight. That was not a workflow problem, it was an architecture problem.
This post is the announcement written the way I explain it on architecture calls: what a SaaS team should demand from a .NET workflow engine, and how the new version answers it. I mark each block as Documented behavior, Architectural recommendation, or Honest limitation, so you can separate facts from my opinion.
What a multi-tenant SaaS needs from a workflow engine
Architectural recommendation. When teams evaluate an enterprise workflow engine for SaaS, they usually compare designers and API surfaces. The tenancy questions surface later, in the security review, and they are the expensive ones. Five of them matter most:
- Can shared and tenant-specific data live side by side, or is tenancy all-or-nothing?
- Can I add a tenant without redeploying or restarting anything?
- Is tenant isolation enforced by the engine and its API, or by discipline in my own code?
- Does isolation cover all engine data, or only the process table?
- Can I adopt tenancy gradually, or does it require a data migration on day one?
| Capability | Why it matters |
|---|---|
| Hybrid tenancy | Shared standard workflows plus per-tenant custom ones |
| Runtime tenant registration | No production restart to onboard a customer |
| API-enforced tenant isolation | Leaks blocked by the engine, not by code review |
| Isolation across all data | Audit compliance: history and inboxes, not just processes |
| Gradual adoption | No day-one migration project |
Hold any engine you evaluate against these five. The rest of this post is how Workflow Engine NEO answers them.
Question 1: can shared and tenant-specific data live side by side
Documented behavior. The engine now implements full hybrid multi-tenancy. Every kind of engine data (workflow schemes, Global Parameters, forms, process records) exists in one of two forms: shared and visible to every tenant, or scoped to one tenant. A record with an empty tenant value is shared; a record created in a tenant context carries that tenant's ID. The Forms Plugin resolves a tenant-specific form first and falls back to the shared one.
Shared (no tenant ID)
├── Standard workflow schemes
├── Shared forms
└── Global Parameters
│ visible to every tenant
┌────┴─────────┬───────────────┐
Tenant A Tenant B Tenant C
processes processes custom scheme
history history custom forms
inbox inbox processes, history
Architectural recommendation. This hybrid model matches how a SaaS grows. One standard approval flow serves most customers; the accounts that pay for custom routing get multi-tenant workflows scoped to them, in the same installation. The alternative, a separate deployment per customized customer, is how SaaS margins die.
Question 2: runtime tenant onboarding while the host is running
Documented behavior. Per the release notes, retrieved 2026-07-21, the tenant registry accepts changes at runtime. This is the dynamic tenant registration piece:
// A new customer signs up. Register them as a tenant, at runtime:
var tenantRegistry = services.GetRequiredService<IWorkflowTenantRegistry>();
var tenants = await tenantRegistry.RegisterTenantsAsync(new WorkflowTenantCreationOptions
{
TenantIds = ["TenantA"],
PersistenceProviderId = PersistenceProviderId.Mssql,
ConnectionString = connectionString
});
// No restart. Existing tenants keep processing their workflows.
var tenant = tenants.Single();
// Offboarding is the same call in reverse. The host keeps running.
await tenantRegistry.UnregisterTenantsAsync(tenant);
Registry-managed tenants start automatically and shut down gracefully when removed. If your application owns tenant lifecycle itself, mark them with WorkflowTenantLifecycleOwnership.External and the registry skips the automatic lifecycle calls. Reads stay consistent while the list changes: IWorkflowTenantSnapshot gives request code an immutable, point-in-time view of registered tenants.
Architectural recommendation. Runtime tenant onboarding becomes one call in your provisioning code, next to creating the tenant database and issuing credentials. Onboarding turns into a database operation, not a deployment event.
Question 3: who enforces tenant isolation
Documented behavior. The tenant boundary is enforced by the API layer, not by convention. A Data API request for another tenant's process returns a not-found result. RPC endpoints check the process tenant against the current HTTP tenant and reject cross-tenant commands. My favorite detail: rpc/is-process-exists answers false for a process that belongs to another tenant. One tenant cannot even probe whether another tenant's data exists.
The same version closes a quieter hole: system Global Parameter types (security settings, LDAP configuration, CORS settings, and similar) are no longer reachable through generic Data API operations.
Architectural recommendation. The tenant header selects context, it does not grant access. Authorization still comes from the WorkflowApiPermissions claim. I wrote about scoping those claims per caller in When to use Data API vs RPC API in Workflow Engine NEO; everything there still holds, now with tenant isolation enforced underneath it.
Question 4: how deep the isolation goes
Documented behavior. Tenant isolation now covers everything the engine stores: schemes, Global Parameters, forms, and every process-related record, from statuses and timers to transition history, inbox entries, and approval history. The Forms Plugin runs tenant-aware on Form Engine 10.0.1.
Architectural recommendation. The record types at the end of that list are the ones to check in any engine you evaluate. Schemes and processes get the attention, but transition history, inbox entries, and approval history are what your auditor asks about, and they leak tenant activity just as well as a process record does. Isolation that stops at the process table is not isolation.
Question 5: what happens to the data you already have
Documented behavior. Nothing changes on its own. Existing records have no tenant value, so under the hybrid model from Question 1 they are shared and stay visible across tenants, exactly as they behaved before the upgrade. Only new records created in a tenant context get a tenant ID.
Architectural recommendation. Upgrade first, then adopt tenancy at the pace your contracts demand, not the pace your engine dictates. Keep standard schemes shared, scope the customer-specific ones, and let historical process data age out as shared records.
Honest limitations
I would rather you hear these from me than from your own upgrade weekend.
-
22.0.0 is a breaking release. The tenant contract changed (custom
IWorkflowTenantimplementations need lifecycle members), severalIPersistenceProvidersignatures now take a tenant ID, and theAssignmentPluginwas removed. Database migrations are mandatory: SQL providers runRunMigrations()before starting the updated runtime, MongoDB needs theupdate_22.0.0.jsindex script run manually. The release notes pair every breaking change with a migration scenario. Budget a real upgrade task, not a version bump. - The Web API and full multi-tenancy are licensed NEO features. Workflow Engine is commercial software with a free tier, source-available under a commercial EULA, not open source, and the Web API does not start without a license key. A trial key from trial.workflowengine.io lets you evaluate it; the free Community Edition covers the embeddable in-process library, not the Web API.
-
Runtime registration does not provision infrastructure.
RegisterTenantsAsyncregisters a tenant against a connection string you supply. Creating the database, running its schema, and storing its secrets remain your provisioning code's job.
Version note
Everything above targets Workflow Engine 22.0.0 (July 16, 2026), verified against the official release notes and the NuGet registry (WorkflowEngine.NETCore-Core 22.0.0) on 2026-07-21. On 21.x and earlier the tenant list is static and the data-layer scoping described here does not exist; do not read this article as documentation for those versions.
The questions are older than the release
Most workflow engine evaluations still focus on designers, BPMN coverage, and APIs. In SaaS, the tenant lifecycle becomes the real architectural bottleneck much later, when changing the answer is already expensive. The five questions above are worth asking before that day arrives, whichever workflow engine for SaaS you end up choosing.
If you want to check our answers against your own architecture, the upgrade details are on our blog, and my team does demo walkthroughs where we build the argument on your tenancy model, not ours.
Top comments (3)
Runtime tenant registration is a meaningful improvement, especially for SaaS platforms where onboarding should never require a production restart.
I also like the hybrid model, but I’d add one architectural caution: API-level tenant isolation is only one layer. Background jobs, caches, direct persistence access, audit exports, and operational tooling all need the same tenant context and enforcement.
The real test is whether a missing or incorrect tenant context fails closed everywhere, not only through the public API.
Mustafa, thank you for this comment, I agree with your main point. А missing tenant context should fail everywhere, not only in the API.
We did push tenant context below the API in this release: timers and process records take their tenant from the process instance, and IPersistenceProvider signatures now require a tenant id, so a provider that ignores it won't compile. But you're right that the engine only covers its own surface. Raw SQL, caches, ops tooling stay the platform's responsibility, and that's where I see most real problems.
And while I have the luck of talking to someone who has clearly been around these systems, let me use it. Would Workflow Engine NEO pass your own technical bar as the main workflow solution for a .NET application? If yes, I'd like to know what would tip the scale for you. And I'm honestly even more interested in the other side: what weaknesses do you see, what's missing, what would stop you, if that's relevant to your work at all. Feel free to be blunt. That kind of feedback is worth more to me than praise.
Thanks in advance,
Mike Lukinov
Thanks, Mike. I spent some time with the live designer and documentation after your reply.
Yes, Workflow Engine NEO would pass my initial technical bar and I would put it into a serious PoC for a .NET SaaS or ERP. The embedded designer, scheme versioning, hybrid tenancy, runtime tenant registration, and explicit tenant context in the persistence contracts are all strong architectural choices.
What would decide whether it became the main workflow solution would be operational behaviour rather than additional designer features:
One design choice I would examine especially carefully is treating an empty tenant ID as shared data. Hybrid tenancy is useful, but I would want global object creation to be an explicit privileged operation, so a missing tenant context fails closed rather than accidentally creating something visible to every tenant.
So my honest answer is: yes, it is a credible candidate. What would tip the scale is proving recovery, observability, idempotency and tenant-level operations under failure—not adding more boxes to the designer. Features attract the first demo; operational behaviour decides whether the engine stays in production for ten years.