Skip to main content
Every job and workflow in Strait is versioned. When you update a job’s configuration, the previous version is snapshotted so that in-flight runs continue to execute with the config they were enqueued under.

Dual Versioning

Each job and workflow has two version identifiers: The integer version is predictable and easy to reason about. The version_id is a 16-character string (4-char prefix + 12-char nanoid using 0-9a-z alphabet) that’s safe to expose in URLs and APIs without leaking ordering information.

Version Lifecycle

On each UpdateJob, the current configuration is snapshotted to the job_versions table before the update is applied. This means:
  • job_versions contains the full config for versions 1, 2, … (N-1)
  • The live jobs table always has the current (latest) version

Atomic Versioning

When a run is enqueued, it captures the job’s current version and version_id:
When the executor picks up the run, it reads the job config at that version from the snapshot table:
This prevents a common race condition: if you update a job’s endpoint URL while runs are queued, those runs still execute against the old endpoint.

Fallback Behavior

If no snapshot exists for the requested version (e.g., version 1 before snapshotting was implemented), the executor falls back to reading the live jobs table. This ensures backwards compatibility.

Version Policy

Each job and workflow has a version_policy that controls how queued runs interact with version updates:

pin (Default)

The safest option. Runs always execute with the exact configuration they were enqueued under. A job update never affects already-queued runs.

latest

Queued runs automatically upgrade to the current version when dequeued. Useful when you want all runs to use the latest config regardless of when they were enqueued.

minor

A middle ground. Queued runs upgrade only if the new version has backwards_compatible = true. This lets you control which updates are safe for in-flight runs.

Setting Version Policy

Or update an existing job:
Version policy is enforced at dequeue time by the worker dispatch path. pin is still the safest default and is applied automatically when no policy is provided.

Version Snapshots

The job_versions table stores a full snapshot of the job configuration at each version:
  • endpoint_url, fallback_endpoint_url
  • max_attempts, timeout_secs
  • tags, payload_schema
  • max_concurrency, execution_window_cron
  • rate_limit_max, rate_limit_window_secs
  • retry_strategy, retry_delays_secs
  • environment_id, group_id
  • enabled
  • version_id, backwards_compatible
Snapshots are created automatically on UpdateJob. The first version (at creation time) is captured when the first update occurs.

Browsing Versions

List all versions of a job:
Response:

Workflow Versioning

Workflows use the same dual version model (version + version_id) and snapshot workflow definitions, including step graphs. Every time you update a workflow via PATCH /v1/workflows/{workflowID}, the version increments and the previous step graph is preserved.

Inspecting versions

  • GET /v1/workflows/{workflowID}/versions — list all version snapshots
  • GET /v1/workflows/{workflowID}/versions/{versionID} — get a specific version
  • GET /v1/workflows/{workflowID}/versions/{versionID}/steps — get the step graph for a version
  • GET /v1/workflows/{workflowID}/active-versions — list versions that have active (pending, running, or paused) runs, with status breakdowns

Breaking change detection

When you update a workflow, the response includes information about in-flight runs on the previous version:
The active_runs_on_previous_version field appears whenever there are non-terminal runs still executing on the version that was just replaced. This gives you immediate visibility into whether your update might affect running workflows. To explicitly acknowledge a breaking update, set breaking_change to true in the request body:
When breaking_change is true and active runs exist on the previous version, Strait records a workflow.updated_breaking audit event with the previous version ID, active run count, and new version number. This makes breaking deployments visible in your audit log.

Run Provenance

Every run records which version it was enqueued under:
This gives you exact traceability: you can always determine which configuration a run executed with, even if the job has been updated many times since.