Skip to main content

0040: Workflow Core Concepts and Patterns

Date: 2025-11-08

Status: Proposed

Context​

Having selected Temporal as our workflow engine (ADR-0039), we need to establish clear definitions and patterns for how developers will create and structure workflows. Temporal's programming model makes a critical distinction between "Workflow" code and "Activity" code. Without a clear standard, developers might place I/O operations or non-deterministic code inside a workflow definition, which would break Temporal's durability guarantees.

We need to formalize these concepts to ensure all workflows are reliable, testable, and maintainable.

Decision​

We will adopt Temporal's core patterns and enforce a strict separation between Workflows and Activities.

  1. Workflows are Code-First Orchestrators:

    • All workflow logic will be written in code (Go or Python), not modeled in a visual tool like BPMN. This aligns with our TDD principles.
    • Workflow functions are deterministic orchestrators. Their only job is to orchestrate the execution of Activities and other Workflows.
    • Workflows must not perform any direct I/O (e.g., network calls, database access) or use non-deterministic functions (e.g., generating random numbers, reading the current time directly).
  2. Activities are the Units of Work:

    • All interaction with the outside world (e.g., calling another microservice's API, querying a database, interacting with a third-party service) must be encapsulated within an Activity.
    • Activities are regular functions that can contain any logic, including I/O. They are executed by "Worker" processes.
    • Temporal manages the execution, retries, and timeouts for Activities, making them resilient.

Consequences​

Positive​

  • Reliability & Durability: This strict separation is what allows Temporal to durably record and replay workflow state, making processes resilient to worker failures.
  • Testability: Workflow logic can be unit-tested in isolation by mocking the Activity interfaces. This makes testing complex orchestration logic fast and simple.
  • Clarity: The roles are unambiguous. Workflows orchestrate; Activities execute. This reduces cognitive load for developers.
  • Scalability: Activity workers can be scaled independently from workflow workers, allowing us to allocate resources where they are most needed.

Negative​

  • Learning Curve: Developers must understand the concept of deterministic workflow code and the constraints it imposes. This is a core part of the Temporal programming model.
  • Increased Boilerplate: A simple operation requires defining both a workflow and an activity, which can feel like extra boilerplate for trivial tasks. This is a necessary trade-off for the reliability of long-running processes.