workflowengineby Optimajet · since 2014

v22.1.0 · six providers, nine databases · one NuGet package and one connection string · included in every product

Workflow Engine keeps its state in the database you already run

Workflow Engine by Optimajet is a .NET library, so it has no datastore of its own and asks you to deploy nothing. Install the provider for your database, pass a connection string, and the engine creates its tables there. Process state, timers, schemes, and history end up next to your business data, inside the backup policy, the failover plan, and the access rules your team already runs.

Persistence layer · one interface, six providersIPersistenceProvider
Your .NET applicationWorkflowRuntimeIN PROCESS.WithPersistenceProvider()IPersistenceProviderone contractSQL Server, Azure SQLProviderForMSSQLPostgreSQLProviderForPostgreSQLMySQLProviderForMySQLMongoDB, Azure Cosmos DBProviderForMongoDBOracleProviderForOracleSQLiteProviderForSQLite

One provider is active in a running application, and the orange outline marks it the way the designer marks a selected element. Swapping the highlighted lane means a different NuGet package and a different connection string. The code above the interface does not change.

Six providers sit behind one interface, so you canswap the database and keep the workflow code

Every process instance, timer, scheme, and history record that Workflow Engine produces has to survive a restart, so the runtime always writes to a database. The question a .NET team actually faces is not whether to use one. It is whose database, and who ends up operating it.

The answer here is yours. A persistence provider translates the runtime's calls into native SQL, or document operations for MongoDB, against a database your organization already manages. Nothing in the engine holds state outside that database, which is why several instances can share one and why a restart loses nothing.

Six providers, nine databases

SQL Server, PostgreSQL, MySQL, MongoDB, Oracle, and SQLite. The SQL Server provider also serves Azure SQL and Azure SQL Managed Instance; the MongoDB provider also serves Azure Cosmos DB.

Initial activity

One interface behind all of them

Every provider implements IPersistenceProvider. Your application code calls WorkflowRuntime, never the database, so the provider is the only thing that knows which engine is underneath.

One NuGet package per database

Install WorkflowEngine.NETCore-ProviderFor{Name} for your database and nothing else. The provider pulls in the migrator it needs on its own.

Tables in your database

RunMigrations() creates the workflow tables and three stored procedures in the database your connection string points at. Your backups, your replication, your retention rules, your access control.

The database is the cluster

In multi-server mode, instances coordinate through the shared database with row locks and alive signals. No message broker, no coordination service, no separate cluster to operate.

Free in every product

The providers are part of the core runtime, not an add-on. The free tier reads and writes the same schema as a licensed production deployment.

Current activity

Six providers cover nine databases

Each provider is its own NuGet package, so you install exactly one and carry no driver you do not use. Two of them cover more than one product. The SQL Server provider serves Azure SQL and Azure SQL Managed Instance as well, and the MongoDB provider serves Azure Cosmos DB, which is how six packages reach nine databases. Runtime floors differ, and the table says so rather than making you find out at restore time.

DatabaseNuGet packageVersionRuns on
SQL Server, Azure SQLWorkflowEngine.NETCore-ProviderForMSSQLv22.1.0.NET Framework 4.6.2+ and all modern .NET
PostgreSQLWorkflowEngine.NETCore-ProviderForPostgreSQLv22.1.0.NET Framework 4.6.2+ and all modern .NET
MySQLWorkflowEngine.NETCore-ProviderForMySQLv22.1.0.NET Framework 4.6.2+ and all modern .NET
MongoDB, Azure Cosmos DBWorkflowEngine.NETCore-ProviderForMongoDBv22.1.0.NET Framework 4.6.2+ and all modern .NET
OracleWorkflowEngine.NETCore-ProviderForOraclev22.1.0.NET Core 3.0 and later
SQLiteWorkflowEngine.NETCore-ProviderForSQLitev22.1.0.NET 8 and laterFor evaluation. Not recommended for production use.

On classic .NET Framework

The SQL Server, PostgreSQL, MySQL, and MongoDB providers target netstandard2.0 and run on .NET Framework 4.6.2 and later, which matters for the applications most likely to be replacing Windows Workflow Foundation.

On modern .NET

All six providers run on current .NET. Oracle and SQLite are the two to check before a legacy port, because neither runs on classic .NET Framework. The table above carries the floor for each one.

In Workflow Engine NEO

The Workflow Engine HTTP API registers the same providers through one dependency injection helper per database, such as AddWorkflowApiPostgres or AddWorkflowApiMssql, so the hosted API and the embedded library make the same storage choice.

Package versions, the .NET Framework and .NET Core install paths, and the sample projects are on the Workflow Engine downloads page.

A connection string and one line of startup code

There is no schema to design, no ORM to configure, and no SQL script to find for your version. You construct the provider for your database, hand it to the runtime, and call RunMigrations() before starting. On first run the tables appear. On every run after that the call finds nothing to do and returns.

Install the provider for your databasebash
dotnet add package WorkflowEngine.NETCore-Core
dotnet add package WorkflowEngine.NETCore-ProviderForPostgreSQL
Point the runtime at itcsharp
var runtime = new WorkflowRuntime()
    .WithPersistenceProvider(new PostgreSQLProvider(connectionString))
    .RunMigrations()
    .AsSingleServer();

await runtime.StartAsync();

Every provider is constructed the same way, so moving a proof of concept from SQLite to the database your team runs in production is a package reference and a type name.

The same call, one provider per databasecsharp
new MSSQLProvider(connectionString)       // SQL Server, Azure SQL, Managed Instance
new PostgreSQLProvider(connectionString)  // PostgreSQL
new MySQLProvider(connectionString)       // MySQL
new MongoDBProvider(connectionString)     // MongoDB, Azure Cosmos DB
new OracleProvider(connectionString)      // Oracle
new SQLiteProvider(connectionString)      // SQLite, evaluation only

The provider package pulls in WorkflowEngine.NETCore-Migrator on its own, so schema setup needs no extra reference. Full startup sequences, including the dependency injection variant, are in the Workflow Engine installation guide.

Workflow state you can read with SELECT

Nothing about the workflow state is opaque. The schema is the short list of tables below plus three stored procedures, created in your default schema, dbo on SQL Server, with GUID keys and ordinary columns. A support engineer can answer "where is invoice 4417 stuck" with a join, an auditor can read the transition history without an export, and your existing monitoring can alert on a timer queue that stops draining. The Every Workflow Engine license stores TenantId on the process record. Your application uses that value to build its tenant model. NEO adds ready multitenancy across the built-in Workflow Engine HTTP API operations.

TableWhat it holds
WorkflowProcessInstanceOne row per process: current activity and state, scheme id, parent and root process, TenantId, creation and last transition dates.
WorkflowProcessInstanceStatusStatus and the lock that keeps two servers from running the same process at once. Status codes run 0 Initialized to 5 Error.
WorkflowProcessInstancePersistenceProcess parameters as key and value rows, one row per parameter.
WorkflowProcessTransitionHistoryThe execution log: every transition, who triggered it, when, and whether it finished.
WorkflowProcessSchemeThe scheme each running process is pinned to, so a scheme change does not rewrite processes already in flight.
WorkflowSchemeThe catalog of scheme definitions the designer reads and writes.
WorkflowProcessTimerPending timers with their fire times. This is the table the timer poller reads.
WorkflowGlobalParameterGlobal parameters and global Code Actions shared across processes.
WorkflowApprovalHistoryApproval Plugin history, recording who approved or rejected what, and in which order.
WorkflowInboxApproval Plugin inbox cache, the per-user task list the plugin reads from.
WorkflowProcessAssignmentAssignment Plugin storage. The plugin is obsolete from v21, and the table stays for existing data.
WorkflowRuntimeThe multi-server registry, one row per runtime instance with its lock, status, next timer time, and last alive signal.
WorkflowSyncThe distributed lock table. Named locks keep cluster-wide operations from overlapping.

The three stored procedures are housekeeping. DropUnusedWorkflowProcessScheme deletes obsolete schemes that no instance still references, DropWorkflowInbox clears one process out of the inbox cache, and spWorkflowProcessResetRunningStatus is the manual recovery for stuck processes, moving them from Running back to Idled.

Schema upgrades your DBA can still review

Automatic schema management has been in the runtime since version 13.0.0, and it runs on FluentMigrator underneath. Teams that let applications create their own tables get a one-line upgrade. Teams whose change-control process forbids that get the same migrations as reviewable SQL, because every provider package ships its scripts as embedded, ordered files. Both paths end at the same schema.

01

The runtime knows its own schema

Each provider ships the migration steps its database needs, written in the SQL dialect of that database. RunMigrations() applies the ones the current runtime version requires.

02

FluentMigrator tracks what ran

Applied steps are recorded in a VersionInfo table. On start the runtime compares that record with the version it needs and applies only the gap.

03

Calling it again costs nothing

The method is idempotent. On an up-to-date database it returns immediately, which is why it is safe to leave in the startup path of every environment.

04

Upgrades are a package bump

Moving to a new Workflow Engine version updates the NuGet reference; the pending migrations run on the next start. Version 22.0.0 ships mandatory database migrations, so this path is the supported one.

Where the call belongs in the startup chaincsharp
var runtime = new WorkflowRuntime()
    .WithPersistenceProvider(new MSSQLProvider(connectionString))
    .RunMigrations();   // after the provider, before StartAsync()

await runtime.StartAsync();

Two caveats worth knowing before you plan an upgrade window. RunMigrations() covers SQL Server, PostgreSQL, MySQL, Oracle, and SQLite; MongoDB manages its schema differently, and its collections and indexes are created by the provider at runtime. And if you add migrations of your own to the same database, start their order numbers at 2 000 000 so they never collide with the built-in ones. The reference is in the database versioning documentation.

The database is the coordination layer

This is where choosing your own database stops being a convenience and starts paying for itself. Scaling Workflow Engine across servers adds no infrastructure. Call AsMultiServer() on each instance, point them at the same database, and they coordinate through it. There is no broker to size, no consensus service to patch, and no vendor cluster in the path between your application and its data.

Timers

Every instance polls for due timers on its own interval, 1000 ms by default, and takes a database lock before executing one. A timer fires once across the cluster.

Liveness

Each instance writes an alive signal into the WorkflowRuntime table. Miss enough of them, the default is 60 intervals, and the instance is marked Terminated by the others.

Recovery

A surviving instance takes over the work of the one that stopped signalling. One healthy instance is enough for the cluster to keep running.

Membership

All instances are equal and there is no master. They never talk to each other directly; the shared database is the only thing they have in common.

Same code on every node, one unique id eachcsharp
var runtime = new WorkflowRuntime("node-01")
    .WithPersistenceProvider(new PostgreSQLProvider(connectionString))
    .RunMigrations()
    .AsMultiServer();

Two honest notes. Every instance sharing a database must run the same settings, and no load balancer is included, so incoming HTTP traffic is still yours to distribute. Multi-server mode is part of the commercial licensing and the free tier runs single-server; the tiers are listed on the Workflow Engine pricing page.

What to settle before the first production deploy

Four constraints decide how this feature lands in a real deployment. They are cheap to design around on day one and expensive to discover later, so they are on this page rather than in a support thread.

Choose the database before production

Switching providers once process instances exist is not supported, and no cross-provider migration tool ships. Each provider stores runtime data in its own native format. Different WorkflowRuntime instances may use different providers, so SQLite in development beside PostgreSQL in production is fine, but one live database does not move to another engine.

SQLite is for evaluation

The SQLite provider exists for local development and single-machine scenarios. It is not recommended for industrial use, it does not run on classic .NET Framework, and this version of SQLite may not work on macOS with Apple Silicon processors.

The engine is not transactional

Workflow Engine is thread-safe but not transactional, and there is no transaction spanning several commands. If a domain write must be atomic with a workflow transition, that atomicity belongs in your code and your database, the same way you handle it elsewhere.

MongoDB is the different one

The MongoDB provider carries the same schema contract in a document model, but RunMigrations() does not apply to it. Five of the six providers implement IMigratable; MongoDB creates collections and indexes at runtime instead.

  • A database is required. Workflow Engine does not run with in-memory state only.
  • The same six providers back every product in the lineup, so the storage decision survives a move from the library to Workflow Engine NEO.
  • A database outside the six is supported through the public IPersistenceProvider interface, with the maintenance of that provider on you.

How the products differ elsewhere, from licensing to the hosted HTTP API, is laid out on the product comparison page.

Common questions

The questions that come up in an infrastructure review: which databases, who creates the tables, what happens on an upgrade, and what the engine cannot do.

  1. Which databases does Workflow Engine support?

    Six persistence provider packages cover nine database and deployment targets: Microsoft SQL Server, Azure SQL Database, Azure SQL Managed Instance, PostgreSQL, MySQL, Oracle, MongoDB, Azure Cosmos DB through its MongoDB-compatible API, and SQLite. Each provider is a separate NuGet package named WorkflowEngine.NETCore-ProviderFor{Name}, and each implements IPersistenceProvider.

  2. Does Workflow Engine need its own database server?

    No. Workflow Engine uses a database that you configure through a persistence provider, and it can be one you already operate. For SQL Server, PostgreSQL, MySQL, Oracle, and SQLite, call RunMigrations() to create or update the provider-specific schema. MongoDB does not use RunMigrations(); follow the release notes for required update and index scripts. No separate Optimajet storage service or message broker is required.

  3. Does the provider create the database tables automatically?

    Not merely by installing a provider package. For SQL Server, PostgreSQL, MySQL, Oracle, and SQLite, an explicit RunMigrations() call creates or updates the provider-specific schema. If the schema is current, no migration scripts are executed. MongoDB does not support RunMigrations(); apply version-specific update and index scripts when the release notes require them.

  4. Can I switch databases after processes are running?

    No. Switching the persistence provider once process instances exist is not supported, and there is no cross-provider migration tool. Each provider stores runtime data in its native format. Pick the database before the first production deployment. Different WorkflowRuntime instances can use different providers, so a development instance on SQLite alongside a production instance on PostgreSQL is fine.

  5. Is multi-database support a paid feature?

    No. The six built-in persistence providers are available in Workflow Engine Free and every edition of Workflow Engine and Workflow Engine NEO. Workflow Engine Free remains limited to personal, non-commercial use. Multi-server deployment is separate: it is available with Workflow Engine Complete and every edition of Workflow Engine NEO; Workflow Engine Free and Workflow Engine Team are single-server.

  6. Can I use a database that is not on the list?

    Yes, but IPersistenceProvider covers runtime persistence rather than the whole built-in provider contract. A complete integration must also supply scheme persistence and generation to a configured WorkflowBuilder, either through IWorkflowProvider or through the separate scheme contracts, and register both with WorkflowRuntime. You own the custom provider and its compatibility with future releases.

  7. Do I need a message broker or a separate cluster to run on several servers?

    No separate message broker or Workflow Engine coordination cluster is required. Each application node runs a Workflow Runtime instance against a shared database; process locks, timer claims, and heartbeat records coordinate the nodes. SQL Server, PostgreSQL, MySQL, MongoDB, and Oracle are documented for multi-server deployment; SQLite is for local or single-node use. A surviving node can recover eligible persisted process state under the configured recovery policy, but it does not resume the exact interrupted instruction or restore temporary in-memory state. The database must meet its own deployment requirements, including MongoDB cluster requirements, and incoming HTTP traffic needs your load balancer.

  8. Can I query workflow data with my normal SQL tools?

    Yes, for SQL Server, PostgreSQL, MySQL, Oracle, and SQLite. Persisted workflow data uses provider-specific tables that you can inspect with native query tools; physical names, functions, and procedures differ, and the three stored procedures described elsewhere are specific to SQL Server. Transition history is queryable when its persistence is enabled. MongoDB uses collections and document queries. Backup, replication, retention, and access-control policies cover workflow data only when configured to include the target database and schema or collections.

  9. Is SQLite suitable for production?

    SQLite is supported. It is useful for evaluation and local or single-machine development, but it is not recommended for production workloads; validate concurrency and durability requirements for your deployment. The current SQLite provider targets .NET 8 and .NET 10 and does not run on classic .NET Framework.

  10. Can one transaction span several workflow commands and domain writes?

    No. Individual provider operations can use local database transactions, but Workflow Engine does not provide one engine-level transaction across several workflow commands or automatically include your domain writes. Coordinate that atomicity in your application and database.

Point it at a database and see what it creates

The fastest way to check any of this is an empty schema. Install the free tier and the provider for your database, call RunMigrations(), and look at what appears. It is the same schema a licensed production deployment uses.

Still comparing options? The Multi-Database Support documentation covers the provider interface and the per-database install steps before you commit to anything.