Skip to main content

Runtimes

WorkflowRuntime is responsible for the following tasks:

  1. Managing workflow state
  2. Persisting events
  3. Recovering state from events
  4. Waking up the workflow at the right moments

Each runtime is created per workflow type, and its creation usually involves implementation-specific elements. WorkflowRuntime interface allows creating a WorkflowInstance based on id and input.

trait WorkflowRuntime[F[_], Ctx <: WorkflowContext, WorkflowId, Input] {

def createInstance(id: WorkflowId, input: Input): F[WorkflowInstance[F, WCState[Ctx]]]

}

Available Runtimes

Below is an overview of the available runtimes, with their strengths and limitations:

RuntimeDescriptionGood ForBad For
PekkoRuntimeUses Pekko Persistance and Cluster Sharding to manage the state and distribution of workload.
  • Scalability
  • Sophisticated requirements
  • Small-scale setups
  • Low complexity use-cases
PostgresRuntimeRelies on PostgreSQL advisory locks, without any in-memory state management.
  • Simplicity
  • Low memory footprint
  • High throughput
  • Frequent state access
InMemoryRuntimeBased on Cats Effect; keeps state in memory without persistence.
  • Fast execution
  • Ephemeral workflows
  • Long-running workflows
  • State durability
InMemorySyncRuntimeVanilla Scala implementation, not thread-safe and lacks persistence.
  • Simple workflows
  • Experimentation
  • Single-threaded scenarios
  • Testing
  • Production use cases

KnockerUpper

Each WorkflowRuntime is usually parameterized by a KnockerUpper implementation which is responsible for waking up the workflow when needed. See Wake-Ups for additional details.