Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.published.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ name: durable-workflow-server
# release whose default names another image). Set DW_SERVER_IMAGE to run
# any other native image, by tag or digest; pin a digest for production
# change control.
x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:3.10.0}
x-server-image: &server-image ${DW_SERVER_IMAGE:-durableworkflow/server:3.11.0}

services:
server:
Expand Down
68 changes: 68 additions & 0 deletions docs/releases/3.11.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Durable Workflow Server 3.11.0 (native)

Server 3.11.0 reuses completed plain timers when redriving a run that failed at
an activity. The successor resumes the failed activity with the original timer
clock. Its immutable images are
`durableworkflow/server:3.11.0` and `ghcr.io/durable-workflow/server:3.11.0`;
the published Compose default selects 3.11.0. Rolling aliases move separately
after the published producer and applicable SDK replay qualification.

## Fired timer reuse

A plain timer before the failed activity must have exactly one ordered
`TimerScheduled` / `TimerFired` pair at a unique step, with matching source timer
identity. The successor records the pair under one new shared timer ID. It
creates no timer row or timer task and does not wait for the timer again.

The reused `TimerFired` records the immediate predecessor in
`reused_from_run_id`. Its `reused_recorded_at` preserves the timer's original
execution time, including after another redrive. The original source history
remains unchanged. Earlier activity and marker steps keep their existing
reuse rules, and only the failed activity is resumed.

Redrive replay timestamps now retain nonzero fractional precision for reused
activities, markers and fired timers. The initial replay anchor retains the
persisted source run start with full precision. Repeated redrives preserve
already-recorded reuse timestamps as recorded. This change cannot reconstruct
fractions omitted by an earlier producer. Deadline formatting is unchanged.

Scope, group, cancellation-cleanup, condition and signal-timeout timers remain
outside this plain-timer slice and refuse as `unsupported_timer`. Incomplete,
reversed, duplicate or mismatched timer pairs refuse as `incomplete_timer_step`.
Step collisions, gaps and invalid failure boundaries retain their explicit
refusals. Cancelled timers and other unsupported history remain refused.
Describe and redrive use the same eligibility decision.

## Upgrade and compatibility

**From 3.10.x, no schema step is needed.** The physical schema remains SQLite 14,
PostgreSQL and MariaDB 15, and MySQL 16. Follow the existing backup and upgrade
guidance, pin the new image, and verify readiness, reported version and worker
registration. Update API replicas consistently before relying on the expanded
redrive eligibility; older replicas retain their earlier refusal rules.

From 3.9.x or earlier, apply the applicable explicit schema steps in the
[3.10 upgrade procedure](https://github.com/durable-workflow/server/releases/tag/3.10.0#upgrade-and-rollback).
This release does not convert a PHP database at startup. The existing takeover
runbook retains its exact historical version, backend and state limits.

Worker protocol `1.20`, control-plane version `2`, codec and command shapes are
unchanged. Existing command-key, completion-byte, storage-admission and
unsupported service-upsert boundaries remain in force. This release does not
add redrive support for signals, updates, child workflows or scoped/group timers.

## Qualification and retained limits

The actual PHP, Python and Rust Worker/cold-process timer-clock proof is tracked
on [#980](https://github.com/durable-workflow/server/issues/980). Source controls
alone do not establish those installed consumer outcomes. Producer source,
backend/corpus, immutable publication, Compose, scan/provenance and exact
published consumer evidence remain separately attributable. Core precision
correction and reference-corpus follow-through retain their separate record in
[Workflow #992](https://github.com/durable-workflow/workflow/issues/992).

The MariaDB registration-timeout investigation
[#1204](https://github.com/durable-workflow/server/issues/1204) remains separate.
Cloud adoption, physical mapping and broader cancellation-policy qualification
retain their existing limits. PHP Server 2.11.8 remains retired and unpatched; see the
[retirement/security notice](../security/retired-php-server-2026-11-13.md).
Loading