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](../../src/modules/Elsa.Persistence.EFCore/Modules/Runtime/WorkflowRuntimePersistenceFeature.cs):
- 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](../../src/modules/Elsa.Persistence.EFCore.Common) and [Elsa.Persistence.EFCore](../../src/modules/Elsa.Persistence.EFCore).
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:
See [src/apps/Elsa.Server.Web/Program.cs](../../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.
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:
-`ApplyTenantId`
-`SetTenantIdFilter`
Tenant conventions are documented in ADRs:
- [ADR 0008: Empty String As Default Tenant ID](../adr/0008-empty-string-as-default-tenant-id.md)
- [ADR 0009: Asterisk Sentinel Value For Tenant-Agnostic Entities](../adr/0009-asterisk-sentinel-value-for-tenant-agnostic-entities.md)
## Structured Log Persistence
Structured log persistence is intentionally separate from EF Core. The active feature plan is [005 structured log persistence](../../specs/005-structured-log-persistence/plan.md).
Persistence vNext is a next-generation, provider-neutral persistence system being developed in parallel with the existing EF Core path. It is currently in early design and not yet used by production Elsa modules.
### Design Goals
- Module authors declare **storage manifests** (storage units, fields, keys, and indexes) once, without referencing any database-specific package.
- Separate **planners** (relational and document) turn manifests into provider-specific plans.
- A **portable document/index store** wraps provider-specific backends so simple modules do not need custom EF Core, SQL, or MongoDB code.
- **Schema versioning** replaces per-provider EF Core migration packages.
Today, use the existing EF Core path for all production Elsa modules. Persistence vNext work belongs in the `011-persistence-vnext` feature branch. Consult the spec and plan before contributing to avoid duplicating EF Core infrastructure for new module entities.