new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Temporal · Concepts · all subjects

design-patterns

826 notes in this subject, read out of this brain and free to use. This is page 12 of 14.

Schedule interval specification in Temporal CLI

In the Temporal CLI, an interval is specified as a string like 45m to mean every 45 minutes, or 6h/5h to mean every 6 hours but at the start of the fifth hour within each period.

Schedule calendar expression in Temporal CLI

In the Temporal CLI, a calendar expression can be specified as either a traditional cron string with five (or six or seven) positional fields, or as JSON with named fields such as year, month, dayOfMonth, dayOfWeek, hour, minute, second, and comment.

Schedule calendar JSON fields and defaults

The following calendar JSON fields are available: year, month, dayOfMonth, dayOfWeek, hour, minute, second, and comment. Each field can contain a comma-separated list of ranges (or the * wildcard), and each range can include a slash followed by a skip value. The hour, minute, and second fields default to 0 while the others default to *. For month, names of months may be used instead of integers (case-insensitive, abbreviations permitted). For dayOfWeek, day-of-week names may be used. The comment field is optional and can be used to include a free-form description of the intent of the calendar spec.

Schedule phase offset for interval alignment

By default, intervals align to the Unix epoch (January 1, 1970 at midnight UTC), so without a phase offset, a 7-day interval would fire every Thursday at whatever time midnight UTC equates to in your local time. Use a phase offset when you need your recurring Schedule to fire at a specific, human-meaningful time. The Schedule fires when this condition is true: ((currentTimestampUTC - phase offset) % interval) == 0. To calculate the phase offset needed: phase offset = referenceTimestampUTC % interval.

Schedule Spec combination features

A Spec can have combinations of multiple intervals and/or calendar expressions to define a specific Schedule. Time bounds can be provided as an absolute start or end time (or both) with a Spec to ensure that no actions are taken before the start time or after the end time. A Spec can contain exclusions in the form of zero or more calendar expressions. If given, a random offset between zero and the maximum jitter is added to each Action time (but bounded by the time until the next scheduled Action).

Schedule timezone handling

By default, calendar-based expressions are interpreted in UTC. Temporal recommends using UTC to avoid various surprising properties of time zones. If you don't want to use UTC, you can provide the name of a time zone. The time zone definition is loaded on the Temporal Server Worker Service from either disk or the fallback embedded in the binary. For more operational control, embed the contents of the time zone database file in the Schedule Spec itself.

Schedule Overlap Policy options

The Overlap Policy controls what happens when it is time to start a Workflow Execution but a previously started Workflow Execution is still running. The options are: Skip (default, nothing happens), BufferOne (starts after current completes, buffer limited to one), BufferAll (unlimited buffer, started sequentially), CancelOther (cancels running execution then starts new one), TerminateOther (terminates running execution and starts new one immediately), and AllowAll (starts any number of concurrent executions, only policy allowing simultaneous runs).

Paused Workflow Execution and Schedule Overlap Policy interaction

A Paused Workflow Execution is still an open Workflow Execution, so it counts as the currently running execution when the Schedule evaluates its Overlap Policy. With Skip, each new scheduled Action is skipped while the previous scheduled Workflow Execution remains Paused. With BufferOne, one Action can wait behind the Paused Workflow Execution. With BufferAll, every matching Action is buffered. With AllowAll, new Workflow Executions can start. With CancelOther, the Schedule requests cancellation of the Paused Workflow Execution. With TerminateOther, the Schedule terminates the Paused Workflow Execution immediately. If you pause a Workflow Execution for investigation and don't want the Schedule to skip or buffer future Actions, pause the Schedule too.

Schedule Catchup Window policy

The Temporal Service might be down or unavailable at the time when a Schedule should take an Action. When it comes back up, the Catchup Window controls which missed Actions should be taken at that point. The default is one year, meaning Actions will be taken unless over one year late. If your Actions are more time-sensitive, you can set the Catchup Window to a smaller value (minimum ten seconds), accepting that an outage longer than the window could lead to missed Actions.

Schedule Pause-on-failure policy

If the pause-on-failure policy is set, a Workflow Execution started by a Schedule that ends with a failure or timeout (but not Cancellation or Termination) causes the Schedule to automatically pause. With the AllowAll Overlap Policy, this pause might not apply to the next Workflow Execution, because the next Workflow Execution might have started before the failed one finished. It applies only to Workflow Executions that were scheduled to start after the failed one finished.

Schedule Backfill functionality

A Schedule can be Backfilled. When a Schedule is Backfilled, all the Actions that would have been taken over a specified time period are taken now (in parallel if the AllowAll Overlap Policy is used; sequentially if BufferAll is used). This might be used to fill in runs from a time period when the Schedule was paused due to an external condition that's now resolved, or a period before the Schedule was created.

Schedule action count limit

A Schedule can be limited to a certain number of scheduled Actions (that is, not trigger immediately). After that it will act as if it were paused.

Schedule LastCompletionResult for overlapping runs

A Workflow started by a Schedule can obtain the completion result from the most recent successful run. For the AllowAll policy with overlapping runs, the last completion result refers to the run that completed most recently at the time that the run in question is started. Failures and timeouts do not affect the last completion result. When a Workflow employs the Continue-As-New feature, LastCompletionResult won't be accessible for this new Workflow iteration.

Schedule LastCompletionResult blob size limitation

A scheduled Workflow Execution may complete with a result up to the maximum blob size (2 MiB by default). However, due to internal limitations, results that are within 1 KiB of this limit cannot be passed to the next execution. A Workflow Execution that returns a result of size 2,096,640 bytes (which is above 2MiB - 1KiB limit) will be allowed to complete successfully, but that value will not be available as a last completion result. This limitation may be lifted in the future.

Schedule LastFailure details retrieval

A Workflow started by a Schedule can obtain the details of the failure of the most recent run that ended at the time when the Workflow in question was started. Unlike last completion result, a successful run does reset the last failure.

Periodic Continue-As-New prevents running on stale code

To prevent long-running Workflows from running on stale versions of code, developers may want to Continue-As-New periodically depending on deployment frequency. This ensures only a couple of code versions are running, avoiding backwards compatibility problems.

Workflow Pause operational control definition

Workflow Pause is an operational control that stops a specific Workflow Execution from making new progress until it is Unpaused. It stops the Workflow without terminating the Workflow Execution or losing Workflow state.

Workflow Pause use cases

Use Workflow Pause when: a downstream dependency is unhealthy and you want to stop the Workflow from continuing until the dependency recovers; you need time to inspect or fix an issue before the Workflow schedules more work; you are rolling out a Worker change and want to hold specific Workflow Executions until the deploy is complete; or you want to prevent a Workflow from continuing without terminating it or losing its current state.

Workflow Pause behavior - dispatch and progress

When a Workflow is Paused: no new Workflow Tasks are dispatched, so Workflow code doesn't make progress; no new Activity Tasks are dispatched, so Activity retries and newly scheduled Activity Tasks don't start.

Workflow Pause behavior - in-flight activities

When a Workflow is Paused, in-flight Activity attempts are not interrupted. Activity attempts that are already running can complete, fail, time out, and Heartbeat normally.

Workflow Pause behavior - events and signals

When a Workflow is Paused: activity completion, failure, and timeout events can be recorded but Workflow code doesn't process them until the Workflow is Unpaused; Signals are accepted and recorded with Signal handlers running after the Workflow is Unpaused.

Workflow Pause behavior - timers and updates

When a Workflow is Paused: Timers keep advancing and Timers that fire while Paused are processed by Workflow code after Unpause; Updates and Queries are rejected.

Workflow Pause behavior - cancel and terminate

When a Workflow is Paused: Cancel requests are recorded but Cancellation takes effect after the Workflow is Unpaused; Terminate requests still terminate the Workflow immediately.

Unpause behavior

When a Workflow is Unpaused: Workflow Tasks and Activity Tasks can be dispatched again; Signals received and Timers that fired while Paused are processed by the Workflow; pending Activity retries can proceed unless the Activity itself is Paused; the Workflow continues from its existing state.

Workflow Pause scope limitations

Workflow Pause applies to a single Workflow Execution only. It does not pause Child Workflows, Activities, Schedules, Task Queues, or Namespaces. Bulk Workflow Pause is not supported.

Workflow Pause does not stop time

Workflow Pause doesn't stop time from passing. Workflow Execution timeouts, Workflow Run timeouts, Activity timeouts, and Timer deadlines continue to advance even when the Workflow is Paused.

Workflow Pause and Schedule overlap policy

A Paused Run is still considered active for Schedule overlap policy decisions.

Workflow Pause and Cron jobs

For Cron jobs, Pause affects the current Run. Missed cron intervals are not backfilled.

Workflow Pause and billing

In Temporal Cloud, pausing a Workflow Execution stops progress but doesn't end the Workflow Execution. Its Event History continues to count toward Active Storage until the Workflow Execution completes, fails, times out, is canceled, or is terminated.

Workflow Pause prerequisites

For self-hosted Temporal, Workflow Pause requires Temporal Server v1.30.0+ with frontend.WorkflowPauseEnabled enabled. The Temporal CLI requires v1.6.0+. Self-hosted UI support requires v2.47.2+. In Temporal Cloud, Pre-release access is invite-only.

Workflow Pause and Activity Pause are separate controls

Workflow Pause and Activity Pause (Activity Operations) are separate controls. Workflow Pause stops progress for a Workflow Execution, while Activity Pause acts on a specific Activity Execution. If a Workflow is Paused, Activity retries are blocked. If both the Workflow and an individual Activity are Paused, both must be Unpaused before that Activity can proceed. Workflow Pause doesn't interrupt Activity attempts already running; use Activity Pause to interrupt a Heartbeating Activity attempt.

Workflow Pause is not an auto-pause policy

Workflow Pause is an operational control that requires manual Pause and Unpause through an operational interface. Operators must manually Pause and Unpause; automatic pause policies are not supported. Workflow Pause is not intended to be called from Workflow code.

Workflow Pause with reset

Resetting a Paused Workflow terminates the current Run and starts a new Run from the selected reset point.

No indicator for in-flight Activity completion

There is no indicator that all in-flight Activity attempts have completed after a Workflow is Paused.

Multiple Activity Executions from Workflow

It is idiomatic to invoke multiple Activity Executions from within a Workflow. It is also idiomatic to either block on the results of the Activity Executions or continue on to execute additional logic, checking for the Activity Execution results at a later time.

Default Parent Close Policy

The default Parent Close Policy option is set to terminate the Child Workflow Execution.

Child Workflow Execution definition

A Child Workflow Execution is a Workflow Execution that is scheduled from within another Workflow using a Child Workflow API.

Eager Workflow Start requirements

Eager Workflow Start requires the workflow starter and Worker to share the same process and client connection. Both must use the same WorkflowClient instance (Java), client.Client (Go), or Client (Python). A Worker using a different connection cannot receive eager tasks from another client.

Eager Workflow Start configuration by language

Enable Eager Workflow Start using: EnableEagerStart: true in Go; setDisableEagerExecution(false) in Java; request_eager_start=True in Python. These settings are passed to StartWorkflowOptions.

Eager Workflow Start fallback behavior

If the server cannot fulfill an eager request (for example, no local slot is available), it falls back silently to normal dispatch. Code does not need to handle this case explicitly.

Eager Workflow Start latency benefits with Local Activities

When combined with Local Activities, Eager Workflow Start achieves approximately 265 ms total-workflow latency, compared to approximately 850 ms baseline. Eager Workflow Start eliminates the Matching Service round-trip on the first Workflow Task, while Local Activities eliminate server round-trips within each Workflow Task.

Eager Workflow Start self-hosted server flag

On self-hosted Temporal Server, Eager Workflow Start may require enabling the dynamic config flag: --dynamic-config-value system.enableEagerWorkflowStart=true. Temporal Cloud and recent versions of the open-source server may enable this by default.

Eager Workflow Start use cases: poor fit

Eager Workflow Start is a poor fit when: Workers are deployed independently from starters (the eager request falls back to normal dispatch, providing no benefit); the TypeScript SDK is being used; or first-response latency matters more than total latency (use Early Return or Early Return + Local Activities instead).

Eager Workflow Start use cases: good fit

Eager Workflow Start is a good fit when: the workflow starter and Worker run in the same deployment unit (for example, a single service that both handles API requests and runs Workers); absolute minimum total-workflow latency is needed and Local Activities are already being used; and the language is Go, Java, or Python.

Eager Workflow Start best practice: resource sharing in co-located deployments

When a Worker runs in the same process as a request handler, they share CPU, memory, and failure domains. A spike in activity execution can slow request handling, and vice versa. Monitor Worker CPU, Workflow Task execution latency, and task queue depth to ensure Worker load does not affect client-facing latency.

Eager Workflow Start best practice: do not rely on eager dispatch always firing

The server falls back to normal dispatch if no local slot is available (for example, the Worker is at capacity). Design the Workflow to work correctly in both eager dispatch and fallback scenarios.

Eager Workflow Start best practice: use non-blocking Worker start

Start the Worker before executing the Workflow so it has an available slot. In Go, use w.Start() and defer w.Stop(). In Python, use async with Worker(...). In Java, call factory.start() before creating the workflow stub.

Eager Workflow Start best practice: combine with Local Activities

Eager Workflow Start should be combined with Local Activities. Eager Workflow Start eliminates the Matching Service overhead on the first Workflow Task; Local Activities eliminate server round-trips within each Workflow Task. Together they provide the greatest total latency reduction.

Eager Workflow Start common pitfall: missing self-hosted feature flag

If the server dynamic config flag system.enableEagerWorkflowStart=true is not set on self-hosted servers, eager dispatch requests are silently ignored and execution falls back to normal dispatch. Verify the flag is set if expected latency improvement is not observed.

Eager Workflow Start common pitfall: distributed deployments

If the process that calls ExecuteWorkflow is not the same process running the Worker, eager dispatch will never succeed. The call still works, but it provides no latency benefit.

Eager Workflow Start common pitfall: Worker started after ExecuteWorkflow

If the Worker is not registered and running before the eager start call, no local slot exists and the request falls back to normal dispatch. The Worker must be started before executing the Workflow.

Eager Workflow Start bypasses Matching Service

Eager Workflow Start eliminates the Temporal Matching Service round-trip by dispatching the first Workflow Task directly to a co-located Worker. Instead of queuing the task and routing through the Matching Service, the server attaches the first Workflow Task to the StartWorkflowExecution response inline. The Worker processes it immediately without a separate polling round-trip. This saves approximately 30–50 ms per Workflow start.

Early Return pattern first-response latency comparison

Early Return with regular Activities achieves first-response latency of approximately 265 ms. By extending Early Return to use Local Activities for Phase 1, the end-to-end first-response time drops to approximately 160 ms, because Phase 1 now runs entirely in-process with no server round-trips.

Early Return + Local Activities pattern overview

The Early Return + Local Activities pattern combines Update-with-Start with Local Activities in the synchronous Phase 1 to reduce first-response latency to approximately 160 ms. Phase 1 (initialization) runs as Local Activities with no server round-trips. Phase 2 (settlement) runs as regular Activities in the background. The client receives its response as soon as Phase 1 completes entirely in-process.

Early Return + Local Activities pattern walkthrough

The pattern works in four steps: (1) The client sends a single UpdateWithStart RPC, which atomically starts the Workflow and delivers the Update in one server call. (2) The Worker picks up the first Workflow Task and executes Phase 1; all Phase 1 Activities are Local Activities running in-process with no additional server calls, completing inside a single Workflow Task. (3) When the Workflow Task completes, the server marks the Update as fulfilled and returns the result to the waiting client, approximately 160 ms after the initial request. (4) The Workflow continues in a new Workflow Task to execute Phase 2 using regular Activities, which run in the background while the client is not blocked.

Early Return pattern problem with regular Activities

The plain Early Return pattern reduces first-response latency, but if Phase 1 uses regular Activities, each Activity incurs server scheduling overhead of approximately 50 ms per call on Temporal Cloud. With two or three Phase 1 Activities, this overhead alone can account for 100-150 ms of the first-response time.

Early Return + Local Activities solution

Run all Phase 1 Activities as Local Activities so they execute in-process within the first Workflow Task, with results available to the Update handler as soon as the task completes and no additional server calls. Phase 2 Activities remain regular Activities, which is acceptable because Phase 2 runs in the background after the client has already received its response.

Early Return + Local Activities when to use

Good fit: user-facing workflows where the first response is more latency-critical than total execution time; Phase 1 consists of short, idempotent validation and initialization steps that fit naturally as Local Activities; Phase 2 is slow (network I/O, external systems) and does not need to be on the client's critical path; you already use or plan to use the Early Return pattern. Poor fit: Phase 1 Activities are long-running or require heartbeating (Local Activities cannot heartbeat); the Workflow's total latency matters more than first-response latency; Phase 1 and Phase 2 cannot be cleanly separated.

Early Return + Local Activities best practices

Keep Phase 1 Local Activities short, completing well within the Workflow Task timeout (default 10 seconds); aim for under 5 seconds total for all Phase 1 work. Design Phase 1 for at-least-once execution: if the Workflow Task that runs Phase 1 fails and retries, all Phase 1 Local Activities re-execute, so operations must be idempotent. Separate Phase 1 and Phase 2 concerns cleanly: the Update handler should wait only on the Phase 1 sentinel flag, not on any Phase 2 state. Set appropriate timeouts for Phase 2 regular Activities to reflect the maximum acceptable settlement time.

Early Return + Local Activities common pitfalls

Putting slow operations in Phase 1 causes Workflow Task timeout and retry, also making the client wait longer for its early response, defeating the pattern's purpose. Non-idempotent Phase 1 operations fail when a retried Workflow Task re-executes all Local Activities in that task; ensure Phase 1 operations are safe to re-run. Ignoring Phase 1 errors in Phase 2 leads to incorrect behavior; always check Phase 1 error state before proceeding to Phase 2, and if Phase 1 failed, run a compensating Activity rather than complete. In Java, newLocalActivityStub and newActivityStub return distinct objects; ensure Phase 1 uses the local stub and Phase 2 uses the regular stub.

Give your agent this brain