* Add ingress rate limiting hooks * Fix ingress rate limiting middleware setup * Harden rate limiter policy validation * Preserve routed endpoints during rate limiting * Address rate limiting review feedback * Address rate limiting Copilot feedback * Register rate limiter services for external policies * Address rate limiting review comments * Keep rate limiter service detection best effort * Address rate limiting review comments * Remove brittle rate limiter validation * Address rate limiting review feedback * Address rate limiting nullable review * Address rate limiting review feedback * Assign ingress rate limit policies when enabled * Refine ingress rate limiting middleware cleanup * Address rate limiting review feedback * Align rate limiting review feedback * Clarify rate limiting policy semantics * Stabilize rate limiting exception tests * Fix rate limiting endpoint matching default
6.8 KiB
Architecture
Elsa Core is a modular workflow platform. The core engine is intentionally small compared with the full host surface: features add management stores, runtime dispatch, APIs, HTTP activities, expression languages, persistence, identity, tenants, diagnostics, and shell integration.
Layered View
flowchart TB
Host["Host app / sample server"] --> Entry["AddElsa / ConfigureElsa"]
Entry --> FeatureGraph["Feature graph"]
FeatureGraph --> Core["Workflow Core"]
FeatureGraph --> Mgmt["Workflow Management"]
FeatureGraph --> Runtime["Workflow Runtime"]
FeatureGraph --> Api["Workflow API"]
FeatureGraph --> Ext["Extension modules"]
Mgmt --> DefStores["Definition and instance stores"]
Runtime --> RuntimeStores["Bookmark, trigger, queue, execution log stores"]
Api --> FastEndpoints["FastEndpoints"]
Ext --> Http["HTTP"]
Ext --> Scheduling["Scheduling"]
Ext --> Expressions["Expressions"]
Ext --> Identity["Identity and tenants"]
DefStores --> Persistence["In-memory or EF Core providers"]
RuntimeStores --> Persistence
The important boundary is that workflow execution concepts live in core, while persisted definitions and runtime orchestration live in management and runtime. API and transport packages are layered on top.
Default Feature Composition
The default umbrella feature is ElsaFeature. It depends on:
MediatorFeatureWorkflowsFeatureFlowchartFeatureDefaultWorkflowRuntimeFeatureWorkflowManagementFeature
When installed, it configures default workflow and activity execution pipelines and registers built-in core activities through workflow management. The public entry point is AddElsa.
Main Runtime Flow
sequenceDiagram
participant Trigger as External stimulus
participant Runtime as Workflow runtime
participant Stores as Runtime stores
participant Mgmt as Management services
participant Core as Workflow runner
participant Logs as Execution logs
Trigger->>Runtime: dispatch trigger/bookmark/workflow
Runtime->>Stores: find triggers or bookmarks
Runtime->>Mgmt: load workflow definition/instance
Runtime->>Core: run workflow execution pipeline
Core->>Core: schedule and invoke activities
Core->>Runtime: produce bookmarks, logs, state changes
Runtime->>Stores: commit triggers/bookmarks/logs/state
Runtime->>Logs: publish runtime notifications
Definitions Versus Instances
- A workflow definition describes what can run. It may originate from C# workflow types, JSON files, imported payloads, blob storage providers, or DSL compilation.
- A workflow instance is a running or historical execution, including workflow state, variables, activity execution state, incidents, status, and logs.
- Management owns definition and instance stores. Runtime owns trigger/bookmark queues and execution.
Activities And Control Flow
Activities are the unit of work. Core activity types live under Elsa.Workflows.Core/Activities. Control flow includes Sequence, If, Switch, Fork, For, ForEach, While, Parallel, Flowchart, StateMachine, and flowchart node activities.
Flowchart execution has a token-centric model documented in ADR 0005, with explicit join behavior documented in ADR 0007.
Management Layer
WorkflowManagementFeature wires:
- workflow definition and instance stores
- workflow serializers and materializers
- workflow definition manager, publisher, importer, exporter, validator
- activity and expression descriptor providers
- host method activities and workflow definition activities
- workflow reference graph services
- default variable type descriptors
The management layer is what Studio and API endpoints use to list, save, publish, import, export, and validate workflows.
Runtime Layer
WorkflowRuntimeFeature wires:
- local runtime and dispatchers
- trigger and bookmark stores
- bookmark queue worker and queue store
- workflow and activity execution log stores
- workflow matcher, starter, invoker, resumer, canceler
- background dispatch and task dispatch services
- graceful shutdown services such as quiescence signal, ingress source registry, and drain orchestrator
- recurring startup and maintenance tasks
The runtime can use in-memory stores by default or EF Core stores when persistence features are installed.
API Layer
WorkflowsApiFeature registers FastEndpoints from the module and depends on workflow management, workflow instances, workflow runtime, and SAS tokens. The default route prefix is elsa/api, defined in ApiEndpointOptions and applied by MapWorkflowsApi in endpoint-routed ASP.NET hosts.
Real-time workflow updates are in RealTimeWorkflowUpdatesFeature and WorkflowInstanceHub.
Persistence Layer
In-memory stores are the default for many features. EF Core provider packages replace store delegates in feature configuration:
- management stores through
WorkflowManagementFeature - runtime stores through
WorkflowRuntimeFeature - identity, tenants, labels, alterations, and key values through their own feature hooks
Provider-specific packages such as SQLite, SQL Server, PostgreSQL, MySQL, and Oracle depend on the shared EF Core module and provide database-specific setup.
Diagnostics Layer
Elsa.Diagnostics.StructuredLogs captures semantic ILogger events, redacts them, keeps recent events, exposes REST endpoints, and streams live events through SignalR. The default store is in-memory; SQLite persistence is available through the relational and SQLite persistence packages.
Elsa.Diagnostics.ConsoleLogs captures raw stdout and stderr from the host process, buffers recent lines, and streams live console output to authorized callers through SignalR. It is separate from structured logs and does not write to durable storage.
See Diagnostics Structured Logs and Diagnostics Console Logs.