Flow Studio
Memory Lifetime
An ExecutionMemory instance is created at the start of every execution run and is garbage-collected when the run ends — or serialized and stored if the execution suspends for HIL. There is exactly one ExecutionMemory per execution at all times.
Lifetime Phases
Created — WorkflowExecutionService creates a new ExecutionMemory and populates Metadata (executionId, processId, tenantId, triggeredBy, startedAt)
→
Active — Execution engine runs nodes in topological order; each node reads from and writes to the shared ExecutionMemory
→
Terminal — Execution completes, fails, or suspends (HIL). Memory is either discarded or serialized.
Terminal States
| Terminal State | What Happens to ExecutionMemory |
|---|---|
| Completed (success) | Memory is discarded — garbage collected. nodeOutputs and globalVariables are gone. |
| Failed (unhandled error) | Memory is discarded. The error is recorded in the execution record but memory is not preserved. |
| Suspended (HIL) | Memory is serialized to JSON and stored in Process_SuspendedExecutions.ExecutionMemoryJson. It is restored when the execution resumes. |
| Cancelled (user or timeout) | Memory is discarded. |
Creation — WorkflowExecutionService
// WorkflowExecutionService.cs (simplified)
public async Task RunAsync(ExecutionRequest request, CancellationToken ct)
{
var memory = new ExecutionMemory(new ExecutionMetadata
{
ExecutionId = request.ExecutionId,
ProcessId = request.ProcessId,
TenantId = request.TenantId,
TriggeredBy = request.TriggeredBy,
StartedAt = DateTimeOffset.UtcNow
});
var ctx = new NodeExecutionContext(memory, /* other services */);
// Run all nodes in topological order — sharing the same memory instance
foreach (var node in _topologicalOrder)
{
await _nodeRunner.RunAsync(node, ctx, ct);
}
// After this loop, memory goes out of scope and is garbage collected
}
HIL Suspension Lifecycle
// When a HIL node suspends the execution:
// 1. ExecutionMemorySerializer serializes the full memory to JSON
// 2. The JSON is saved to Process_SuspendedExecutions
// 3. The in-memory ExecutionMemory object is discarded
// On resume:
// 1. WorkflowExecutionService reads ExecutionMemoryJson from Process_SuspendedExecutions
// 2. ExecutionMemorySerializer.Deserialize() restores the ExecutionMemory
// 3. Execution continues from the suspended node with the restored memory
Memory Growth
ExecutionMemory grows as nodes run. For long workflows that produce large outputs at each step, memory consumption can become significant. Key guidelines:
| Guideline | Detail |
|---|---|
| Avoid storing large binary data in output | Store URLs or references to binary data (e.g., blob storage), not the binary itself |
| Avoid storing entire database result sets | Store IDs or aggregated summaries, not full rows |
| HIL serialization has a size limit | If ExecutionMemoryJson exceeds the configured limit (default 50MB), the serialization step will fail with a clear error |
ExecutionMemory is not a cache. It is not designed for storage of large datasets across nodes. For large data transfers within a workflow, store the data in a temporary location (blob storage, temp database table) and pass a reference (URL, ID) through ExecutionMemory.