* Add codebase wiki * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Document resilient restore workflow --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
6.4 KiB
Persistence
Elsa uses replaceable stores. Most features default to memory stores, then provider packages replace those stores with EF Core or other persistence implementations. Diagnostics structured logs also have a separate relational/SQLite persistence path that deliberately does not use EF Core.
Store Replacement Pattern
Feature classes expose store factories. Persistence features replace those factories during Configure().
Example from EFCoreWorkflowRuntimePersistenceFeature:
- replace
WorkflowRuntimeFeature.TriggerStore - replace
BookmarkStore - replace
BookmarkQueueStore - replace
WorkflowExecutionLogStore - replace
ActivityExecutionLogStore - replace key-value store
Management persistence follows the same idea for definition and instance stores.
EF Core Shared Infrastructure
Shared EF Core infrastructure lives in Elsa.Persistence.EFCore.Common and Elsa.Persistence.EFCore.
Important base types:
- PersistenceFeatureBase
- PersistenceShellFeatureBase
- CombinedPersistenceShellFeatureBase
- ElsaDbContextBase
PersistenceFeatureBase registers IDbContextFactory<TDbContext>, migration options, tenant-aware context factory decoration, and tenant model handlers.
EF Core Module Slices
The shared EF Core module contains slices for:
Each slice has a DbContext, configurations, store implementations, feature classes, and shell feature classes.
Provider Packages
Provider packages configure database-specific EF Core options and migrations:
- Elsa.Persistence.EFCore.Sqlite
- Elsa.Persistence.EFCore.SqlServer
- Elsa.Persistence.EFCore.PostgreSql
- Elsa.Persistence.EFCore.MySql
- Elsa.Persistence.EFCore.Oracle
Combined provider shell features such as SqliteWorkflowPersistenceShellFeature let modular hosts configure workflow persistence once and share settings with dependent definition, instance, and runtime persistence features.
Typical Host Configuration
The reference server configures SQLite persistence for management and runtime separately:
elsa.UseWorkflowManagement(management =>
{
management.UseEntityFrameworkCore(ef => ef.UseSqlite());
});
elsa.UseWorkflowRuntime(runtime =>
{
runtime.UseEntityFrameworkCore(ef => ef.UseSqlite());
});
See src/apps/Elsa.Server.Web/Program.cs.
Migrations
EF Core migrations are controlled by feature options such as RunMigrations. The base persistence feature registers startup tasks that run migrations when enabled.
Migration-related files:
When adding an entity or changing persisted shape, check every provider package and test provider-specific migration behavior where practical.
Tenant Awareness
EF Core persistence decorates IDbContextFactory<TDbContext> with TenantAwareDbContextFactory<TDbContext> and registers model/saving handlers:
ApplyTenantIdSetTenantIdFilter
Tenant conventions are documented in ADRs:
- ADR 0008: Empty String As Default Tenant ID
- ADR 0009: Asterisk Sentinel Value For Tenant-Agnostic Entities
Structured Log Persistence
Structured log persistence is intentionally separate from EF Core. The active feature plan is 005 structured log persistence.
Packages:
- Elsa.Diagnostics.StructuredLogs: core capture, API, hub, provider/store contracts, default in-memory store.
- Elsa.Diagnostics.StructuredLogs.Persistence.Relational: provider-neutral relational store, SQL builder, mapper, retention service, write buffer.
- Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite: SQLite connection factory, dialect, FluentMigrator runner, startup migration/cleanup service.
This path uses explicit SQL and FluentMigrator. It stores timestamps as UTC ISO-8601 text and JSON payloads as text in SQLite.
Adding A Store
When adding a new store implementation:
- Identify the feature contract that owns the store.
- Keep the core module provider-neutral.
- Add the concrete store in the persistence/provider module.
- Replace the feature's store factory in the persistence feature.
- Add unit tests for store-specific query behavior if logic is nontrivial.
- Add integration tests for provider behavior, migrations, and multi-target concerns where practical.
Persistence Risk Checklist
- Does the change affect multiple target frameworks?
- Does it need provider-specific migrations?
- Does it preserve tenant filtering?
- Does it update both definition and instance stores if both shapes changed?
- Does it require API/client DTO updates?
- Does it alter runtime recovery, bookmark, or trigger semantics?
- Does it need retention, cleanup, or migration documentation?