AnnouncementsIntroducing Arkoren

    Menu

    Workflows Overview

    Coordinate long-running processes with typed workflows and replay-safe steps.

    What's on this page
    1. Distinguish workflow coordination from steps, signals, queue jobs, and scheduled tasks.
    2. Define and register typed work with replay restrictions and a required run limit.
    3. Recognize idempotency, retention, and durable-handoff boundaries before choosing a driver.
    On this page

    A signup can send a welcome message now and wait days for confirmation. A workflow keeps that process together as a named Go function. Each execution is a run, with your identifier, a status, and a typed result.

    With a durable driver, recorded history lets the engine rebuild an interrupted run on another worker. The memory driver executes the same definitions locally but loses runs when the process exits. Choose and configure a driver before using the client examples.

    Process Boundaries

    A queue job is one unit of background work. A scheduled task starts work at a time. A workflow coordinates several actions and decisions over its lifetime: send a message, wait for confirmation, then activate an account or let the invitation expire.

    A step performs an external effect, such as sending mail or updating a database. A signal supplies a typed value from outside the run. The workflow function coordinates those operations; it does not perform their I/O itself. Durable drivers can suspend between operations without keeping your application goroutine alive throughout the wait.

    Durability is not an atomic transaction with your database or mail service. An effect can succeed before its step result is recorded, causing another attempt after recovery. Make step effects idempotent. Likewise, committing a database change and starting a workflow are two separate operations unless your application provides a durable handoff, such as an outbox.

    Defining Work

    For onboarding, pass a small payload that both client and worker can encode. These examples use arkoren.dev/core/service/workflow:

    type User struct {
    	ID    int    `json:"id"`
    	Email string `json:"email"`
    }

    Your application supplies sendWelcome, with signature func(context.Context, User) (string, error). It sends through your mail service, honors cancellation, and tolerates repeated calls for the same user. Declare it as a step so the driver can record its result:

    var SendWelcome = workflow.NewStep("send-welcome", sendWelcome)

    A workflow can return that result directly. Give every workflow a positive MaxDuration; registration rejects a definition without it.

    var Onboard = workflow.New("onboard", func(c *workflow.Context, user User) (string, error) {
    	return c.Step(SendWelcome, user)
    }, func(definition *workflow.Builder) {
    	definition.MaxDuration(96 * time.Hour)
    })

    This baseline ends after sending the welcome message. To keep the run open for confirmation, replace its body with the version in Signals and Waiting. The whole-run limit must exceed that legitimate wait as well as the steps around it.

    Definitions are immutable once built. Builder callbacks run synchronously, once in order, on a fresh draft; retaining that draft cannot reconfigure the published definition. A supplied nil callback or a callback panic propagates. Expanded nil or empty callback slices supply no edits.

    Focused snippets in this category show error results but omit routine propagation. Complete function bodies and examples about recovery keep their checks; application code must handle the remaining errors.

    Replay Rules

    An engine can replay the workflow function from the beginning, supplying recorded operation results to reconstruct its state. Given those same results, the function must make the same calls in the same order.

    • Put network, database, file, and other I/O in workflow steps. Do not read mutable global state in coordination code.
    • Use c.Now() and c.UUID() instead of reading the clock or random numbers directly. The driver makes their values stable across replay.
    • Do not start goroutines or use your own channels in the workflow function. Use durable waits instead. These rules also apply to Select callbacks and to code using the native context from c.Raw().
    • Inputs and outputs must round-trip through the shared codec. The default is encoding/json/v2; a time.Duration field does not marshal, so represent payload durations as an integer number of seconds.

    A workflow change can invalidate histories still in flight. A new workflow name keeps old and new coordination separate. An input version works only when you retain the old branch and route existing runs to compatible workers; changing a version field alone does not migrate history. Check the provider rollout limits before replacing workers.

    MaxDuration ends an overlong run with workflow.ErrTimeout; it cannot forcibly terminate arbitrary Go code. Retention controls how long finished records stay available where the provider supports it. Retained records, rather than the identifier alone, provide duplicate-start protection.

    Registering Definitions

    A worker needs the workflow and every step it can execute. Validate them together before constructing the driver or starting its host:

    registry, err := workflow.Handlers(Onboard, SendWelcome)

    Handle err at startup. Workflows and steps share a name namespace: names contain 1–64 lowercase letters, digits, or inner hyphens. Registration reports duplicate names, nil functions, invalid declarations, and missing run limits. Constructors retain the first declaration error; NewSignal instead panics for an invalid signal name, so declare signals at startup too.

    The registry snapshots definitions and policies, not the services captured by their functions. Client and worker must agree on names, payload types, and codec. Custom codecs must produce valid JSON and support concurrent use. Set them on both RegistryBuilder.Codec and ClientBuilder.Codec; configuring one role does not configure the other.

    Native drivers register work through a worker host; their construction belongs on Drivers.

    Once the driver is ready, start and inspect a run. For declarations and options, see the workflow API reference.

    Open a bulk documentation archive?

    This file contains every guide in its scope, not API declarations. Loading it all into an agent can exhaust its context window and increase processing time and cost. For coding tasks, start with the index and read only the relevant pages.

    Use the full archive for offline indexing, bulk processing, or deliberate large-context use.

    Browse the index instead
    Open archive