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.