# Execute a workflow
result = await client.execute_workflow(
    GreetingWorkflow.run,
    name,
    id="my-workflow",
    task_queue=TASK_QUEUE_NAME,
)
```

**Excerpt of code used to configure the Worker, referencing the constant
defined with the Task Queue name in Python**

```python
worker = Worker(
    client,
    task_queue=TASK_QUEUE_NAME,
    workflows=[GreetingWorkflow],
    activities=[activities.say_hello],
)
```

</TabItem>
<TabItem value="go" label="Go">

**Excerpt of code used to define a constant with the Task Queue name in Go**

```go
package app 

const TaskQueueName = "my-taskqueue-name"
```

**Excerpt of code used to start the Workflow, referencing the constant defined with the Task Queue name in Go**

```go
options := client.StartWorkflowOptions{
    ID:        "my-workflow",
    TaskQueue: app.TaskQueueName,
}

run, err := c.ExecuteWorkflow(ctx, options, ProcessOrderWorkflow, input)
```

**Excerpt of code used to configure the Worker, referencing the constant defined with the Task Queue name in Go**

```go
w := worker.New(c, app.TaskQueueName, worker.Options{})
```

</TabItem>
<TabItem value="java" label="Java">

**Excerpt of code used to define a constant with the Task Queue name in Java**

```java
package app;

public class Constants {

  public static final String taskQueueName = "my-task-queue-name";

}
```

**Excerpt of code used to start the Workflow, referencing the constant defined with the Task Queue name in Java**

```java
WorkflowOptions options = WorkflowOptions.newBuilder()
        .setWorkflowId("my-workflow")
        .setTaskQueue(Constants.taskQueueName)
        .build();

MyWorkflow workflow = client.newWorkflowStub(MyWorkflow.class, options);
```

**Excerpt of code used to configure the Worker, referencing the constant defined with the Task Queue name in Java**

```java
Worker worker = factory.newWorker(Constants.taskQueueName);
```

</TabItem>
<TabItem value="typescript" label="Typescript">

**Excerpt of code used to define a constant with the Task Queue name in TypeScript**

```typescript
const TASK_QUEUE_NAME = 'my-taskqueue-name';
```

**Excerpt of code used to start the Workflow, referencing the constant defined with the Task Queue name in TypeScript**

```typescript

// additional code would follow

await client.workflow.start(OrderProcessingWorkflow, {
  args: [order],
  taskQueue: TASK_QUEUE_NAME,
  workflowId: `workflow-order-${order.id},`,
});
```

**Excerpt of code used to configure the Worker, referencing the constant defined with the Task Queue name in TypeScript**

```typescript

// additional code would follow

const worker = await Worker.create({
  taskQueue: TASK_QUEUE_NAME,
  connection,
  workflowsPath: require.resolve('./workflows'),
  activities,
});
```

</TabItem>
<TabItem value="dotnet" label=".NET">

**Excerpt of code used to define a constant with the Task Queue name in C# and .NET**

```csharp
public static class WorkflowConstants
{
    public const string TaskQueueName = "translation-tasks";
}
```

**Excerpt of code used to start the Workflow, referencing the constant defined with the Task Queue name in C# and .NET**

```csharp
var options = new WorkflowOptions(
            id: "translation-workflow",
            taskQueue: WorkflowConstants.TaskQueueName);

// Run workflow
var result = await client.ExecuteWorkflowAsync(
    (TranslationWorkflow wf) => wf.RunAsync(input),
    options);
```

**Excerpt of code used to configure the Worker, referencing the constant defined with the Task Queue name in C# and .NET**

```csharp
using var worker = new TemporalWorker(
    client,
    new TemporalWorkerOptions(WorkflowConstants.TaskQueueName)
    .AddAllActivities(activities)
    .AddWorkflow<TranslationWorkflow>());
```

</TabItem>

</Tabs>

However, it’s not always possible to do define the Task Queue name in a constant, such as when the Client used
to start the Workflow is running on another system or is implemented in a
different programming language.

---

## Task Queues

This page discusses [Task Queues](#task-queue) including [where to set Task Queues](#set-task-queue) and [Task Ordering](#task-ordering).

## What is a Task Queue? {#task-queue}

A Task Queue is a lightweight, dynamically allocated queue that one or more [Worker Entities](/workers#worker-entity) poll for [Tasks](/tasks).
There are three types of Task Queues: Activity Task Queues, Workflow Task Queues, and Nexus Task Queues.

<CaptionedImage
    src="/diagrams/task-queue.svg"
    title="Task Queue component"
    />

A Nexus Endpoint creates an entry point that separates callers from the underlying Nexus Task Queue.
The Nexus callers only interact with the Nexus Endpoint.
This endpoint routes Nexus Requests to a target Task Queue that's polled by a Nexus Worker.

<CaptionedImage
    src="/img/encyclopedia/workers/nexus-task-queue.png"
    title="Nexus Endpoint component"
    />

Task Queues are lightweight components that don’t require explicit registration.
They’re created on demand when a Workflow Execution, Activity, or Nexus Operation is invoked, and/or when a Worker Process subscribes to start polling.
When a named Task Queue is created, individual Task Queues for Workflows, Activities, and Nexus are created using the same name.
A Temporal Application can use, and the Temporal Service can maintain, an unlimited number of Task Queues.

Workers poll for Tasks in Task Queues via synchronous RPC.
This implementation offers several benefits:

- A Worker Process polls for a message only when it has spare capacity, avoiding overloading itself.
- In effect, Task Queues enable load balancing across many Worker Processes.
- Task Queues enable [Task Routing](/task-routing), which is the routing of specific Tasks to specific Worker Processes or even a specific process.
- Activity Task Queues support server-side throttling, which enables you to limit the Task dispatching rate to the pool of Worker Processes while still supporting Task dispatching at higher rates when spikes happen.
- Workflow and Activity Tasks persist in a Task Queue.
  When a Worker Process goes down, the messages remain until the Worker recovers and can process the Tasks.
- Nexus and Query Tasks are not persisted.
  Instead, they are sync matched when, and only when, polled by a Worker.
  Sync matching immediately matches and delivers a Task to an available Worker without persisting a Task to the Service database.
  The caller is responsible to retry failed operations.
  Caller Workflows that invoke Nexus Operations will automatically retry Nexus Tasks until exceeding the Schedule-to-Close timeout.
- Worker Processes do not need to advertise themselves through DNS or any other network discovery mechanism.
- Worker Processes connect directly to the Temporal Service for secure communication without needing to open exposed ports.

Any Worker can pick up any Task on a given Task Queue.
You must ensure that if a Worker accepts a Task that it can process that task using one of its registered Workflows, Activities, or Nexus Operation handlers.
This means that all Workers listening to a Task Queue must register all Workflows, Activities, and Nexus Operations that live on that Queue.

There are two exceptions to this "Task Queue Workers with identical registrations" rule.
First, Worker Versioning may be used.
During Worker upgrade binary rollouts, it's okay to have temporarily misaligned registrations.
Second, dynamic Workflows or Activity components may be used.
If a Task arrives with a recognized method signature, the Worker can use a pre-registered dynamic stand-in.

When Workers don't have a registered Workflow, Activity, Nexus Operation, or dynamic Workflow or Activity component for a given Task, the Task will fail with a "Not Found" error.

- "Not Found" Workflow Tasks and Activity Tasks are treated as _retryable_ errors.
- "Not Found" Nexus Operation handlers are _non-retryable_ and must be manually retried from the caller Workflow.

#### Where to set Task Queues {#set-task-queue}

There are five places where the name of the Task Queue can be set by the developer.

1. A Task Queue must be set when spawning a Workflow Execution:

   - [How to start a Workflow Execution using the Temporal CLI](/cli/workflow#start)
   - [How to start a Workflow Execution using the Go SDK](/develop/go/temporal-client#start-workflow-execution)
   - [How to start a Workflow Execution using the Java SDK](/develop/java/temporal-client#start-workflow-execution)
   - [How to start a Workflow Execution using the PHP SDK](/develop/php/temporal-client#start-workflow-execution)
   - [How to start a Workflow Execution using the Python SDK](/develop/python/temporal-client#start-workflow-execution)
   - [How to start a Workflow Execution using the TypeScript SDK](/develop/typescript/temporal-client#start-workflow-execution)
   - [How to start a Workflow Execution using the .NET SDK](/develop/dotnet/temporal-client#start-workflow)

2. A Task Queue name must be set when creating a Worker Entity and when running a Worker Process:

   - [How to run a development Worker using the Go SDK](/develop/go/core-application#develop-worker)
   - [How to run a development Worker using the Java SDK](/develop/java/core-application#run-a-dev-worker)
   - [How to run a development Worker using the PHP SDK](/develop/php/core-application#run-a-dev-worker)
   - [How to run a development Worker using the Python SDK](/develop/python/core-application#run-a-dev-worker)
   - [How to run a development Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-dev-worker)
   - [How to run a development Worker using the .NET SDK](/develop/dotnet/core-application#run-worker-process)
   - [How to run a Temporal Cloud Worker using the Go SDK](/develop/go/core-application#run-a-temporal-cloud-worker)
   - [How to run a Temporal Cloud Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-temporal-cloud-worker)

   Note that all Worker Entities listening to the same Task Queue name must be registered to handle the exact same Workflows Types, Activity Types, and Nexus Operations.

   If a Worker Entity polls a Task for a Workflow Type or Activity Type it does not know about, it will fail that Task.
   However, the failure of the Task will not cause the associated Workflow Execution to fail.

3. A Task Queue name can be provided when spawning an Activity Execution:

   This is optional.
   An Activity Execution inherits the Task Queue name from its Workflow Execution if one is not provided.

   - [How to start an Activity Execution using the Go SDK](/develop/go/core-application#activity-execution)
   - [How to start an Activity Execution using the Java SDK](/develop/java/core-application#activity-execution)
   - [How to start an Activity Execution using the PHP SDK](/develop/php/core-application#activity-execution)
   - [How to start an Activity Execution using the Python SDK](/develop/python/core-application#activity-execution)
   - [How to start an Activity Execution using the TypeScript SDK](/develop/typescript/core-application#activity-execution)
   - [How to start an Activity Execution using the .NET SDK](/develop/dotnet/core-application#activity-execution)

4. A Task Queue name can be provided when spawning a Child Workflow Execution:

   This is optional.
   A Child Workflow Execution inherits the Task Queue name from its Parent Workflow Execution if one is not provided.

   - [How to start a Child Workflow Execution using the Go SDK](/develop/go/child-workflows)
   - [How to start a Child Workflow Execution using the Java SDK](/develop/java/child-workflows)
   - [How to start a Child Workflow Execution using the PHP SDK](/develop/php/continue-as-new)
   - [How to start a Child Workflow Execution using the Python SDK](/develop/python/child-workflows)
   - [How to start a Child Workflow Execution using the TypeScript SDK](/develop/typescript/child-workflows)
   - [How to start a Child Workflow Execution using the .NET SDK](/develop/dotnet/child-workflows)

5. A Task Queue name can be provided when creating a Nexus Endpoint.
   Nexus Endpoints route requests to the target Task Queue.
   Nexus Workers poll the target Task Queue to handle the Nexus Tasks, such as starting or cancelling a Nexus Operation.

   - [How to run a Nexus Worker using the Go SDK](https://docs.temporal.io/develop/go/nexus#register-a-nexus-service-in-a-worker)
   - [How to run a Nexus Worker using the Java SDK](https://docs.temporal.io/develop/java/nexus#register-a-nexus-service-in-a-worker)

#### Task ordering

Task Queues can be scaled by adding partitions.
By [default](/references/dynamic-configuration#service-level-rps-limits) each Task Queue has 4 partitions.

Task Queues with a single partition are almost always first-in, first-out, with rare edge case exceptions.
However, using a single partition limits you to low- and medium-throughput use cases.

In Task Queues with multiple partitions, each task is assigned to a random partition.
Generally partitions will act as FIFO queues, so once a task queue builds up a backlog, the sync match (tasks that can be dispatched immediately) rate will drop to nearly zero because the task queue will instead dispatch tasks from the backlog (i.e. async matches) first.

:::note

This section is on the ordering of individual Tasks, and does not apply to the ordering of Workflow Executions, Activity Executions, or [Events](/workflow-execution/event#event) in a single Workflow Execution.
The order of Events in a Workflow Execution is guaranteed to remain constant once they have been written to that Workflow Execution's [History](/workflow-execution/event#event-history).

:::

---

## Task Routing and Worker Sessions

This page discusses the following:

- [Task Routing](#task-routing)
- [Worker Sessions](#worker-session)

## What is Task Routing? {#task-routing}

Task Routing is simply when a Task Queue is paired with one or more Workers, primarily for Activity Task Executions.

This could also mean employing multiple Task Queues, each one paired with a Worker Process.

Task Routing has many applicable use cases.

Some SDKs provide a [Session API](#worker-session) that provides a straightforward way to ensure that Activity Tasks are executed with the same Worker without requiring you to manually specify Task Queue names.
It also includes features like concurrent session limitations and worker failure detection.

### Flow control

A Worker that consumes from a Task Queue asks for an Activity Task only when it has available capacity, so it is never overloaded by request spikes.
If Activity Tasks get created faster than Workers can process them, they are backlogged in the Task Queue.

### Throttling

The rate at which each Activity Worker polls for and processes Activity Tasks is configurable per Worker.
Workers do not exceed this rate even if it has spare capacity.
There is also support for global Task Queue rate limiting.
This limit works across all Workers for the given Task Queue.
It is frequently used to limit load on a downstream service that an Activity calls into.

### Specific environments

In some cases, you might need to execute Activities in a dedicated environment.
To send Activity Tasks to this environment, use a dedicated Task Queue.

#### Route Activity Tasks to a specific host

In some use cases, such as file processing or machine learning model training, an Activity Task must be routed to a specific Worker Process or Worker Entity.

For example, suppose that you have a Workflow with the following three separate Activities:

- Download a file.
- Process the file in some way.
- Upload a file to another location.

The first Activity, to download the file, could occur on any Worker on any host.
However, the second and third Activities must be executed by a Worker on the same host where the first Activity downloaded the file.

In a real-life scenario, you might have many Worker Processes scaled over many hosts.
You would need to develop your Temporal Application to route Tasks to specific Worker Processes when needed.

Code samples:

- [Go file processing example](https://github.com/temporalio/samples-go/tree/main/fileprocessing)
- [Java file processing example](https://github.com/temporalio/samples-java/tree/main/core/src/main/java/io/temporal/samples/fileprocessing)
- [PHP file processing example](https://github.com/temporalio/samples-php/tree/master/app/src/FileProcessing)

#### Route Activity Tasks to a specific process

Some Activities load large datasets and cache them in the process.
The Activities that rely on those datasets should be routed to the same process.

In this case, a unique Task Queue would exist for each Worker Process involved.

#### Workers with different capabilities

Some Workers might exist on GPU boxes versus non-GPU boxes.
In this case, each type of box would have its own Task Queue and a Workflow can pick one to send Activity Tasks.

### Multiple priorities

If your use case involves more than one priority, you can create one Task Queue per priority, with a Worker pool per priority.

### Versioning

Task Routing is the simplest way to version your code.

If you have a new backward-incompatible Activity Definition, start by using a different Task Queue.

## What is a Worker Session? {#worker-session}

A Worker Session is a feature provided by some SDKs that provides a straightforward API for [Task Routing](#task-routing) to ensure that Activity Tasks are executed with the same Worker without requiring you to manually specify Task Queue names.
It also includes features like concurrent session limitations and Worker failure detection.

- [How to use Worker Sessions](/develop/go/sessions)

---

## Tasks

This page discusses the following:

- [Task](#task)
- [Workflow Task](#workflow-task)
- [Workflow Task Execution](#workflow-task-execution)
- [Activity Task](#activity-task)
- [Activity Task Execution](#activity-task-execution)
- [Nexus Task](#nexus-task)
- [Nexus Task Execution](#nexus-task-execution)

## What is a Task? {#task}

A Task is the context that a Worker needs to progress with a specific [Workflow Execution](/workflow-execution), [Activity Execution](/activity-execution), or a [Nexus Task Execution](#nexus-task-execution).

There are three types of Tasks:

- [Workflow Task](#workflow-task)
- [Activity Task](#activity-task)
- [Nexus Task](#nexus-task)

## What is a Workflow Task? {#workflow-task}

A Workflow Task is a Task that contains the context needed to make progress with a Workflow Execution.

- Every time a new external event that might affect a Workflow state is recorded, a Workflow Task that contains the event is added to a Task Queue and then picked up by a Workflow Worker.
- After the new event is handled, the Workflow Task is completed with a list of [Commands](/workflow-execution#command).
- Handling of a Workflow Task is usually very fast and is not related to the duration of operations that the Workflow invokes.

### What is a Workflow Task Execution? {#workflow-task-execution}

A Workflow Task Execution occurs when a [Worker](/workers#worker-entity) picks up a [Workflow Task](#workflow-task) and uses it to make progress on the execution of a [Workflow Definition](/workflow-definition) (also known as a Workflow function).

## What is an Activity Task? {#activity-task}

An Activity Task contains the context needed to proceed with an [Activity Task Execution](#activity-task-execution).
Activity Tasks largely represent the Activity Task Scheduled Event, which contains the data needed to execute an Activity Function.

If Heartbeat data is being passed, an Activity Task will also contain the latest Heartbeat details.

### What is an Activity Task Execution? {#activity-task-execution}

An Activity Task Execution occurs when a [Worker](/workers#worker-entity) uses the context provided from the [Activity Task](#activity-task) and executes the [Activity Definition](/activity-definition) (also known as the Activity Function).

The [ActivityTaskScheduled Event](/references/events#activitytaskscheduled) corresponds to when the Temporal Service puts the Activity Task into the Task Queue.

The [ActivityTaskStarted Event](/references/events#activitytaskstarted) corresponds to when the Worker picks up the Activity Task from the Task Queue.

Either [ActivityTaskCompleted](/references/events#activitytaskcompleted) or one of the other Closed Activity Task Events corresponds to when the Worker has yielded back to the Temporal Service.

The API to schedule an Activity Execution provides an "effectively once" experience, even though there may be several Activity Task Executions that take place to successfully complete an Activity.

Once an Activity Task finishes execution, the Worker responds to the Temporal Service with a specific Event:

- ActivityTaskCanceled
- ActivityTaskCompleted
- ActivityTaskFailed
- ActivityTaskTerminated
- ActivityTaskTimedOut

## What is a Nexus Task? {#nexus-task}

A Nexus Task represents a single Nexus request to start or cancel a Nexus Operation.
The Nexus Task includes details such as the Nexus Service and Nexus Operation names, and other information required to process the Nexus request.
The Temporal Worker triggers the registered Operation handler based on the Nexus task information.

### What is a Nexus Task Execution? {#nexus-task-execution}

A Nexus Task Execution occurs when a Worker uses the context provided from the Nexus Task and executes an action associated with a Nexus Operation which commonly includes starting a Nexus Operation using it's Nexus Operation handler plus many additional actions that may be performed on a Nexus Operation.

The NexusOperationScheduled Event corresponds to when the Temporal Service records the Workflow's intent to schedule an operation.

The NexusOperationStarted Event corresponds to when the Worker picks up the Nexus Task from the Task Queue, starts an asynchronous Nexus Operation, and returns an Operation token to the caller indicating the asynchronous Nexus Operation has started.

Either NexusOperationCompleted or one of the other Closed Nexus Operation Events corresponds to when the Nexus Operation has reached a final state due to successfully completing the operation or unsuccessfully completing the operation in the case of a failure, timeout, or cancellation.

A Nexus Operation Execution appears to the caller Workflow as a single RPC, while under the hood the Temporal Service may issue several Nexus Tasks to attempt to start the Operation.
Hence, a Nexus Operation Handler implementation should be idempotent.
The WorkflowRunOperation provided by the SDK leverages Workflow ID based deduplication to ensure idempotency and provide an "effectively once" experience.

A Nexus Task Execution completes when a Worker responds to the Temporal Service with either a RespondNexusTaskCompleted or RespondNexusTaskFailed call, or when the Task times out.

The Temporal Service interprets the outcome and determines whether to retry the Task or record the progress in a History Event:

- NexusTaskCompleted
- NexusTaskFailed

---

## Worker Shutdown Behavior


When a Worker shuts down, it stops polling for new tasks and begins the shutdown sequence.
In the case of in-flight Workflow Tasks, shutdown may cause them to fail if they aren’t completed in time, after exhausting Retry Policy attempts.

There are two types of shutdown behavior that can occur, depending on whether an idea of “graceful shutdown” is configured.

## Graceful Shutdown

Graceful shutdown configures how much time a Worker has to complete its current task before shutting down.
An Activity is able to determine that the Worker it’s running on is being shut down, through the Activity context.

> Core SDKs - `graceful_shutdown_period`

> Go - `WorkerStopTimeout`

> Java - `shutdown()` followed by `awaitTermination(timeout, unit)`

### Workflow tasks

Any in-flight Workflow Tasks are (attempted to be) completed.
The only reason they may not immediately, is if Workflow code is (incorrectly) blocking, or because of Local Activities (see below).

### Activities

Activities are allowed to complete during the graceful shutdown period.

### Local Activities

Because Local Activities run within a Workflow Task, current and future Local Activities within the same Workflow Task will be allowed to run and complete, assuming there is no additional command to yield to.

If the Local Activity is unable to complete by the graceful shutdown period, the Local Activity attempt is sent a cancel signal.
In this case, no new Local Activities will be retried or started, and the Worker is shut down.
The Worker still waits for the current Workflow Task to complete, meaning you can eventually hit your Workflow Task or execution timeout, unless another Worker is spun up.

## Non-Graceful Period Shutdown

This behavior is for either no graceful period being specified, or if the shutdown has taken longer than the configured graceful period.
In all cases, the Activity context is canceled and the Worker will finish shutdown when the current Workflow Task completes (with either success or failure).

:::note
Go and Core SDKs behave differently when we pass task timeout and the Activity or Local Activity is still running:

**Go** - The shutdown completes, but the Activity will continue to run and use a slot.

**Core** - The Worker shutdown will not complete while the Activity completes.
:::

### Local Activities

The Local Activity is sent a cancel signal, then the Workflow Task heartbeats stop, and no new Local Activities will be retried or started.
The Worker still waits for the current Workflow Task to complete, meaning you can eventually hit your Workflow Task or execution timeout, unless another Worker is spun up.

## General Developer Guidance

- Ensure Activities and Local Activities **honor context cancellation** or other shutdown signals.
- Expect that **long or hung Local Activities may block shutdown** unless you fail early.
  It is recommended that Local Activities should already generally be used for short Activities.

---

## Worker Versioning

This page defines some of the underlying concepts used in [Worker Versioning](/production-deployment/worker-deployments/worker-versioning):

- [Worker Deployments](#deployments)
- [Worker Deployment Versions](#deployment-versions)
- [Versioning Behaviors](#versioning-behaviors)
- [Versioning Definitions](#versioning-definitions)
- [Versioning Statuses](#versioning-statuses)
- [Continue-as-new, Child Workflow, and Retry Semantics](#inheritance-semantics)

## Worker Deployments {#deployments}

A Worker Deployment is a logical service that groups similar Workers together for unified management.
Each Deployment has a name (such as your service name) and supports versioning through a series of Worker Deployment Versions.

## Worker Deployment Versions {#deployment-versions}

A Worker Deployment Version represents an iteration of a Worker Deployment.
Each Deployment Version consists of Workers that share the same code build and environment.
When a Worker starts polling for Workflow and Activity Tasks, it reports its Deployment Version to the Temporal Server.

## Versioning Behaviors {#versioning-behaviors}

You can declare each Workflow type to have a **Versioning Behavior**, either Pinned or Auto-Upgrade, in your Workflow configuration using an SDK or the CLI.

To learn more about implementing Worker Versioning, see our [Worker Versioning in production](production-deployment/worker-deployments/worker-versioning) page.

### Pinned Workflows {#pinned}

A **Pinned** Workflow is guaranteed to complete on a single Worker Deployment Version. You can mark a Workflow Type as pinned when you register it by adding an additional Pinned parameter. If you need to move a pinned Workflow to a new version, use [`temporal workflow update-options`](/cli/workflow#update-options).

### Auto-Upgrade Workflows {#auto-upgrade}

An **Auto-Upgrade** Workflow will move to the latest Worker Deployment Version automatically whenever you change the current version. Auto-upgrade Workflows are not restricted to a single Deployment Version and need to be kept replay-safe manually, i.e. with [patching](/workflow-definition#workflow-versioning).

### Actvity behavior across versions

There are a few scenarios to consider for your Activities when you're handling your Worker Deployment versions.

- Activities generally start on the Worker Deployment Version of their Workflow which means:
  - For Pinned Workflows, an Activity starts on the pinned version.
  - For Auto-Upgrade Workflows, an Activity starts on the Target Worker Deployment Version of the Workflow. In this case, Workflow Execution moves to its Target Version immediately before starting the Activity if the Target Version is different from the last used Version. The Target Worker Deployment Version of a Workflow is the Current or Ramping Version of the Workflow's Task Queue, depending on the Ramp Percentage and Workflow ID.

There is an exception where you will have **Independent Activities**. Independent Activities are specific to Worker Versioning. They start on the Current or Ramping Version of their own Task Queue independently from their Workflow.

- For a Pinned Workflow, Independent Activities are Activities that start on a Task Queue that's not a member of the calling Workflow's Pinned Worker Deployment Version.
- For an Auto-Upgrade Workflow, Independent Activities are Activities that start on a Task Queue that's not a member of the calling Workflow's Target Worker Deployment Version.

Since Independent Activities aren't part of a Workflow's version, they can run in a few different ways:

- The Activity Task Queue is running in a separate Worker Deployment that only has the Independent Activity.
- The Independent Activity is in an unversioned Task Queue.
- The Independent Activity is in a separate Worker Deployment that has its own Workflows, but other Workflows reuse the Activity from other Worker Deployments.

## Versioning Definitions

- **Current Worker Deployment Version**: The version where Workflows are routed to unless they were previously pinned on a different version. Other versions can continue polling to allow pinned Workflows to finish executing or in case you need to roll back. If no current version is specified, the default is unversioned.
- **Ramping Worker Deployment Version**: The version where a configurable percentage of Workflows are routed to unless they were previously pinned on a different version. The ramp percentage can be in the range [0, 100]. Workflows that don't go to the Ramping Version will go to the Current Version. If no Ramping Version is specified, 100% of new Workflows and Auto-Upgrade Workflows will go to the Current Version.
- **Target Worker Deployment Version**: The version your Workflow will move to next. This could be the Deployment's Current Version or the Ramping Version. For example, if an Auto-Upgrade Workflow was running on Version A, the Current Version is B, and there is a 5% ramp to C, there is a 95% chance that its Target Version is B and 5% that it's C.

## Versioning Statuses {#versioning-statuses}

A Worker Deployment Version moves through the following states:

1. **Inactive**: The version exists because a Worker with that version has polled the server. If this version never becomes Active, it will never be Draining or Drained.
2. **Active**: The version is either Current or Ramping, so it is accepting new Workflows and existing auto-upgrade Workflows.
3. **Draining**: The version has open pinned Workflows running on it, but stopped being Current or Ramping, usually because a newer version has been deployed. It is possible to be Draining and have no open pinned Workflows for a short time, since the drainage status is updated only periodically.
4. **Drained**: The version was draining and now all the pinned Workflows that were running on it are closed. Closed Workflows may still re-run some code paths if they are [Queried](https://docs.temporal.io/sending-messages#sending-queries) within their [Retention Period](https://docs.temporal.io/temporal-service/temporal-server#retention-period) and Workers with that version are still polling.

## Continue-as-new, Child Workflow, and Retry Semantics {#inheritance-semantics}

When Workflows start new runs (e.g. by continuing-as-new or retrying) the new run may inherit their versioning behavior. This section explains how inheritance works across different Workflow execution patterns.

### Ways Workflows Start New Runs

A Workflow can start a new run through:

- Starting a [Child Workflow](https://docs.temporal.io/child-workflows)
- Invoking [Continue-As-New](https://docs.temporal.io/workflow-execution/continue-as-new)
- Retrying per its [Retry Policy](https://docs.temporal.io/encyclopedia/retry-policies)
- Starting another iteration of a [Cron Job](https://docs.temporal.io/cron-job) (superseded by [Schedules](https://docs.temporal.io/schedule))

### Inheritance Rules Overview

Auto-upgrade Workflows never inherit versions.
By default, Pinned workflows will pass their version to any Pinned children.

This section provides more detail on specific inheritance scenarios.

### Inheritance by Scenario

#### Child Workflows

**When Parent is Pinned:**

- Child inherits the parent's version if the child's Task Queue belongs to that version
- Child's first Workflow task executes in the same version as its parent
- If child is also Pinned: child remains Pinned to the inherited version for its lifetime
- If child is Auto-Upgrade: child's behavior changes to Auto-Upgrade after the first task completes
- If child's Task Queue is not in the same Worker Deployment as parent: no inheritance occurs, child starts on Current Version of its task queue

**When Parent is Auto-upgrade:**

- Child inherits no initial Versioning Behavior
- Child starts on the Current Version of its Worker Deployment like all new Workflow executions

#### Continue-As-New

**When Original Workflow is Pinned:**

- The Pinned version is inherited across the Continue-As-New chain
- If the new run's Task Queue is not in the same Worker Deployment as the original Workflow: no inheritance occurs, new run starts on Current Version of its task queue

**When Original Workflow is Auto-upgrade:**

- No version inheritance occurs

#### Retries

**Inheritance Conditions (all must be met):**

- The retried run is effectively pinned at the time of retry
- The retried run inherited a pinned version when it started (i.e., it is a child of a pinned parent, or a Continue-As-New of a pinned run)
- The retried run is running on a Task Queue in the inherited version

**When Conditions Not Met:**

- No version inheritance occurs

#### Cron Jobs

- **Never inherit** versioning behavior or version

### Versioning Override Inheritance

- Children, crons, retries, and continue-as-new inherit the source run's override **if**:
  - The override is pinned, **AND**
  - The new Workflow's Task Queue belongs to the override version
- Override inheritance is evaluated separately and takes precedence over inherited base version

---

## What is a Temporal Worker?

This page discusses the following:

- [Worker](#worker)
- [Worker Program](#worker-program)
- [Worker Entity](#worker-entity)
- [Worker Identity](#worker-identity)
- [Worker Process](#worker-process)

## What is a Worker? {#worker}

In day-to-day conversations, the term Worker is used to denote either a [Worker Program](#worker-program), a [Worker Process](#worker-process), or a [Worker Entity](/workers#worker-entity).
Temporal documentation aims to be explicit and differentiate between them.

## What is a Worker Program? {#worker-program}

A Worker Program is the static code that defines the constraints of the Worker Process, developed using the APIs of a Temporal SDK.

:::info

- [How to run a development Worker using the Go SDK](/develop/go/core-application#develop-worker)
- [How to run a development Worker using the Java SDK](/develop/java/core-application#run-a-dev-worker)
- [How to run a development Worker using the PHP SDK](/develop/php/core-application#run-a-dev-worker)
- [How to run a development Worker using the Python SDK](/develop/python/core-application#run-a-dev-worker)
- [How to run a development Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-dev-worker)
- [How to run a development Worker using the .NET SDK](/develop/dotnet/core-application#run-worker-process)

- [How to run a Temporal Cloud Worker using the Go SDK](/develop/go/core-application#run-a-temporal-cloud-worker)
- [How to run a Temporal Cloud Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-temporal-cloud-worker)

:::

## What is a Worker Entity? {#worker-entity}

A Worker Entity is the individual Worker within a Worker Process that listens to a specific Task Queue.

A Worker Entity listens and polls on a single Task Queue.
A Worker Entity contains a Workflow Worker and/or an Activity Worker, which makes progress on Workflow Executions and Activity Executions, respectively.

**Can a Worker handle more Workflow Executions than its cache size or number of supported threads?**

Yes it can.
However, the trade off is added latency.

Workers are stateless, so any Workflow Execution in a blocked state can be safely removed from a Worker.
Later on, it can be resurrected on the same or different Worker when the need arises (in the form of an external event).
Therefore, a single Worker can handle millions of open Workflow Executions, assuming it can handle the update rate and that a slightly higher latency is not a concern.

**Operation guides:**

- [How to tune Workers](/develop/worker-performance)

## What is a Worker Identity? {#worker-identity}

Workers have an associated identifier that helps identify the specific Worker instance.
By default, Temporal SDKs set a Worker Identity to `${process.pid}@${os.hostname()}`, which combines the Worker's process ID (`process.pid`) and the hostname of the machine running the Worker (`os.hostname()`).

The Worker Identity is visible in various contexts, such as Workflow History and the list of pollers on a Task Queue.

You can use the Worker Identity to aid in debugging operational issues.
By providing a user assigned identifier, you can trace issues back to specific Worker instances.

**What are some limitations of the default identity?**

While the default identity format may seem sensible, it often proves to be of limited usefulness in cloud environments.
Some common issues include:

- **Docker containers**: When running Workers inside Docker containers, the process ID is always `1`, as each container typically runs a single process. This makes the process identifier meaningless for identification purposes.
- **Random hostnames**: In some cloud environments, such as Amazon ECS (Elastic Container Service), the hostname is a randomly generated string that does not provide any meaningful information about the Worker's execution context.
- **Ephemeral IP addresses**: In certain cases, the hostname might be set to an ephemeral IP address, which can change over time and does not uniquely identify a Worker instance.

**What are some recommended approaches?**

It is recommended that you ensure that the Worker Identity can be linked back to the corresponding machine, process, execution context, or log stream.
In some execution environments, this might require that you explicitly specify the Worker Identity.

Here are some approaches:

- **Use environment-specific identifiers**: Choose an identifier that is specific to your execution environment. For example, when running Workers on Amazon ECS, you can set the Worker Identity to the ECS Task ID, which uniquely identifies the task running the Worker.
- **Include relevant context**: Incorporate information that helps establish the context of the Worker, such as the deployment environment (`staging` or `production`), region, or any other relevant details.
- **Ensure uniqueness**: Make sure that the Worker Identity is unique within your system to avoid ambiguity when debugging issues.
- **Keep it concise**: While including relevant information is important, try to keep the Worker Identity concise and easily readable to facilitate quick identification and troubleshooting.

## What is a Worker Process? {#worker-process}

<CaptionedImage
    src="/diagrams/worker-and-server-component.svg"
    title="Component diagram of a Worker Process and the Temporal Server"
    />

A Worker Process is responsible for polling a [Task Queue](/task-queue), dequeueing a [Task](/tasks#task), executing your code in response to a Task, and responding to the [Temporal Service](/temporal-service) with the results.

More formally, a Worker Process is any process that implements the Task Queue Protocol and the Task Execution Protocol.

- A Worker Process is a Workflow Worker Process if the process implements the Workflow Task Queue Protocol and executes the Workflow Task Execution Protocol to make progress on a Workflow Execution.
  A Workflow Worker Process can listen on an arbitrary number of Workflow Task Queues and can execute an arbitrary number of Workflow Tasks.
- A Worker Process is an Activity Worker Process if the process implements the Activity Task Queue Protocol and executes the Activity Task Processing Protocol to make progress on an Activity Execution.
  An Activity Worker Process can listen on an arbitrary number of Activity Task Queues and can execute an arbitrary number of Activity Tasks.

**Worker Processes are external to a Temporal Service.**
Temporal Application developers are responsible for developing [Worker Programs](#worker-program) and operating Worker Processes.
Said another way, the [Temporal Service](/temporal-service) (including the Temporal Cloud) doesn't execute any of your code (Workflow and Activity Definitions) on Temporal Service machines. The Temporal Service is solely responsible for orchestrating [State Transitions](/workflow-execution#state-transition) and providing Tasks to the next available [Worker Entity](/workers#worker-entity).

While data transferred in Event Histories is [secured by mTLS](/self-hosted-guide/security#encryption-in-transit-with-mtls), by default, it is still readable at rest in the Temporal Service.

To solve this, Temporal SDKs offer a [Data Converter API](/dataconversion) that you can use to customize the serialization of data going out of and coming back in to a Worker Entity, with the net effect of guaranteeing that the Temporal Service cannot read sensitive business data.

In many of our tutorials, we show you how to run both a Temporal Service and one Worker on the same machine for local development.
However, a production-grade Temporal Application typically has a _fleet_ of Worker Processes, all running on hosts external to the Temporal Service.
A Temporal Application can have as many Worker Processes as needed.

A Worker Process can be both a Workflow Worker Process and an Activity Worker Process.
Many SDKs support the ability to have multiple Worker Entities in a single Worker Process.
(Worker Entity creation and management differ between SDKs.)
A single Worker Entity can listen to only a single Task Queue.
But if a Worker Process has multiple Worker Entities, the Worker Process could be listening to multiple Task Queues.

<CaptionedImage
    src="/diagrams/worker-and-server-entity-relationship.svg"
    title="Entity relationship diagram (meta model) of Worker Processes, Task Queues, and Tasks"
/>

Worker Processes executing Activity Tasks must have access to any resources needed to execute the actions that are defined in Activity Definitions, such as the following:

- Network access for external API calls.
- Credentials for infrastructure provisioning.
- Specialized GPUs for machine learning utilities.

The Temporal Service itself has [internal workers](https://temporal.io/blog/workflow-engine-principles/#system-workflows-1910) for system Workflow Executions.
However, these internal workers are not visible to the developer.

---

## Temporal Cron Job

This page discusses [Cron Job](#temporal-cron-job) including [Cron Schedules](#cron-schedules), [Time Zones](#cron-job-time-zones), and [how to stop a Cron Schedule](#stop-cron-schedules).

## What is a Temporal Cron Job? {#temporal-cron-job}

:::note

We recommend using [Schedules](/schedule) instead of Cron Jobs.
Schedules were built to provide a better developer experience, including more configuration options and the ability to update or pause running Schedules.

:::

A Temporal Cron Job is the series of Workflow Executions that occur when a Cron Schedule is provided in the call to spawn a Workflow Execution.

- [How to set a Cron Schedule using the Go SDK](/develop/go/schedules#temporal-cron-jobs)
- [How to set a Cron Schedule using the Java SDK](/develop/java/schedules#cron-schedule)
- [How to set a Cron Schedule using the PHP SDK](/develop/php/schedules#temporal-cron-jobs)
- [How to set a Cron Schedule using the Python SDK](/develop/python/schedules#temporal-cron-jobs)
- [How to set a Cron Schedule using the TypeScript SDK](/develop/typescript/schedules#temporal-cron-jobs)

<CaptionedImage
    src="/diagrams/temporal-cron-job.svg"
    title="Temporal Cron Job timeline" />

A Temporal Cron Job is similar to a classic unix cron job.
Just as a unix cron job accepts a command and a schedule on which to execute that command, a Cron Schedule can be provided with the call to spawn a Workflow Execution.
If a Cron Schedule is provided, the Temporal Server will spawn an execution for the associated Workflow Type per the schedule.

Each Workflow Execution within the series is considered a Run.

- Each Run receives the same input parameters as the initial Run.
- Each Run inherits the same Workflow Options as the initial Run.

The Temporal Server spawns the first Workflow Execution in the chain of Runs immediately.
However, it calculates and applies a backoff (`firstWorkflowTaskBackoff`) so that the first Workflow Task of the Workflow Execution does not get placed into a Task Queue until the scheduled time.
After each Run Completes, Fails, or reaches the [Workflow Run Timeout](/encyclopedia/detecting-workflow-failures#workflow-run-timeout), the same thing happens: the next run will be created immediately with a new `firstWorkflowTaskBackoff` that is calculated based on the current Server time and the defined Cron Schedule.

The Temporal Server spawns the next Run only after the current Run has Completed, Failed, or has reached the Workflow Run Timeout.
This means that, if a Retry Policy has also been provided, and a Run Fails or reaches the Workflow Run Timeout, the Run will first be retried per the Retry Policy until the Run Completes or the Retry Policy has been exhausted.
If the next Run, per the Cron Schedule, is due to spawn while the current Run is still Open (including retries), the Server automatically starts the new Run after the current Run completes successfully.
The start time for this new Run and the Cron definitions are used to calculate the `firstWorkflowTaskBackoff` that is applied to the new Run.

A [Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout) is used to limit how long a Workflow can be executing (have an Open status), including retries and any usage of Continue As New.
The Cron Schedule runs until the Workflow Execution Timeout is reached or you terminate the Workflow.

<CaptionedImage
    src="/diagrams/temporal-cron-job-failure-with-retry.svg"
    title="Temporal Cron Job Run Failure with a Retry Policy" />

## Cron Schedules {#cron-schedules}

Cron Schedules are interpreted in UTC time by default.

The Cron Schedule is provided as a string and must follow one of two specifications:

**Classic specification**

This is what the "classic" specification looks like:

```
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
│ │ │ │ │
│ │ │ │ │
* * * * *
```

For example, `15 8 * * *` causes a Workflow Execution to spawn daily at 8:15 AM UTC.
Use the [crontab guru site](https://crontab.guru/) to test your cron expressions.

### `robfig` predefined schedules and intervals

You can also pass any of the [predefined schedules](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-Predefined_schedules) or [intervals](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-Intervals) described in the [`robfig/cron` documentation](https://pkg.go.dev/github.com/robfig/cron/v3).

```
| Schedules              | Description                                | Equivalent To |
| ---------------------- | ------------------------------------------ | ------------- |
| @yearly (or @annually) | Run once a year, midnight, Jan. 1st        | 0 0 1 1 *     |
| @monthly               | Run once a month, midnight, first of month | 0 0 1 * *     |
| @weekly                | Run once a week, midnight between Sat/Sun  | 0 0 * * 0     |
| @daily (or @midnight)  | Run once a day, midnight                   | 0 0 * * *     |
| @hourly                | Run once an hour, beginning of hour        | 0 * * * *     |
```

For example, "@weekly" causes a Workflow Execution to spawn once a week at midnight between Saturday and Sunday.

Intervals just take a string that can be accepted by [time.ParseDuration](http://golang.org/pkg/time/#ParseDuration).

```
@every <duration>
```

## Time zones {#cron-job-time-zones}

_This feature only applies in Temporal 1.15 and up_

You can change the time zone that a Cron Schedule is interpreted in by prefixing the specification with `CRON_TZ=America/New_York` (or your [desired time zone from tz](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)). `CRON_TZ=America/New_York 15 8 * * *` therefore spawns a Workflow Execution every day at 8:15 AM New York time, subject to caveats listed below.

Consider that using time zones in production introduces a surprising amount of complexity and failure modes!
**If at all possible, we recommend specifying Cron Schedules in UTC (the default)**.

If you need to use time zones, here are a few edge cases to keep in mind:

- **Beware Daylight Saving Time:** If a Temporal Cron Job is scheduled around the time when daylight saving time (DST) begins or ends (for example, `30 2 * * *`), **it might run zero, one, or two times in a day**! The Cron library that we use does not do any special handling of DST transitions. Avoid schedules that include times that fall within DST transition periods.
  - For example, in the US, DST begins at 2 AM. When you "fall back," the clock goes `1:59 … 1:00 … 1:01 … 1:59 … 2:00 … 2:01 AM` and any Cron jobs that fall in that 1 AM hour are fired again. The inverse happens when clocks "spring forward" for DST, and Cron jobs that fall in the 2 AM hour are skipped.
  - In other time zones like Chile and Iran, DST "spring forward" is at midnight. 11:59 PM is followed by 1 AM, which means `00:00:00` never happens.
- **Self Hosting note:** If you manage your own Temporal Service, you are responsible for ensuring that it has access to current `tzdata` files. The official Docker images are built with [tzdata](https://docs.w3cub.com/go/time/tzdata/index) installed (provided by Alpine Linux), but ultimately you should be aware of how tzdata is deployed and updated in your infrastructure.
- **Updating Temporal:** If you use the official Docker images, note that an upgrade of the Temporal Service may include an update to the tzdata files, which may change the meaning of your Cron Schedule. You should be aware of upcoming changes to the definitions of the time zones you use, particularly around daylight saving time start/end dates.
- **Absolute Time Fixed at Start:** The absolute start time of the next Run is computed and stored in the database when the previous Run completes, and is not recomputed. This means that if you have a Cron Schedule that runs very infrequently, and the definition of the time zone changes between one Run and the next, the Run might happen at the wrong time. For example, `CRON_TZ=America/Los_Angeles 0 12 11 11 *` means "noon in Los Angeles on November 11" (normally not in DST). If at some point the government makes any changes (for example, move the end of DST one week later, or stay on permanent DST year-round), the meaning of that specification changes. In that first year, the Run happens at the wrong time, because it was computed using the older definition.

## How to stop a Temporal Cron Job {#stop-cron-schedules}

A Temporal Cron Job does not stop spawning Runs until it has been Terminated or until the [Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout) is reached.

A Cancellation Request affects only the current Run.

Use the Workflow Id in any requests to Cancel or Terminate.

---

## Dynamic Handler

This page discusses [Dynamic Handler](#dynamic-handler).

## What is a Dynamic Handler? {#dynamic-handler}

Temporal supports Dynamic Workflows, Activities, Signals, and Queries.

:::note

Currently, the Temporal SDKs that support Dynamic Handlers are:

- [Java](/develop/java/message-passing#dynamic-handler)
- [Python](/develop/python/message-passing#dynamic-handler)
- [.NET](/develop/dotnet/message-passing#dynamic-handler)
- [Go](/develop/go/core-application#set-a-dynamic-workflow)
- [Ruby](/develop/ruby/message-passing#dynamic-handler)

:::

These are unnamed handlers that are invoked if no other statically defined handler with the given name exists.

Dynamic Handlers provide flexibility to handle cases where the names of Workflows, Activities, Signals, or Queries aren't known at run time.

:::caution

Dynamic Handlers should be used judiciously as a fallback mechanism rather than the primary approach.
Overusing them can lead to maintainability and debugging issues down the line.

Instead, Workflows, Activities, Signals, and Queries should be defined statically whenever possible, with clear names that indicate their purpose.
Use static definitions as the primary way of structuring your Workflows.

Reserve Dynamic Handlers for cases where the handler names are not known at compile time and need to be looked up dynamically at runtime.
They are meant to handle edge cases and act as a catch-all, not as the main way of invoking logic.

:::

---

## Patching

This page discusses [Patching](#patching).

## What is Patching? {#patching}

A Patch defines a logical branch in a Workflow for a specific change, similar to a feature flag.
It applies a code change to new Workflow Executions while avoiding disruptive changes to in-progress Workflow Executions.
When you want to make substantive code changes that may affect existing Workflow executions, create a patch. Note that there's no need to patch [Pinned Workflows](/worker-versioning).

### Detailed Description of the `patched()` Function

This applies to the `patched()` function in the Python, .NET, and Ruby SDKs.

#### Behavior When Not Replaying

If the execution is not replaying, when it encounters a call to `patched()`, it first checks the event history.

- If the patch ID is not in the event history, the execution adds a marker to the event history, upserts a search attribute, and returns `true`. This happens in the first block of the patch ID.
- If the patch ID is in the event history, the execution doesn't modify the history, and returns `true`.
  This happens in a patch ID's subsequent blocks, because the event history was updated in the first block.

There is a caveat to this behavior, which we will cover below.

#### Behavior When Replaying With Marker Before-Or-At Current Location

If the execution is replaying and has a call to `patched()`, and if the event history has a marker from a call to `patched()` in the same place (which means it will match the original event history), then it writes a marker to the replay event history and returns `true`.

This is similar to the behavior of the non-replay case, and also happens in a given patch ID's first block.

If the code has a call to `patched()`, and the event history has a marker with that Patch ID earlier in the history, it will return `true` and will not modify the replay event history.

This is also similar to the behavior of the non-replay case, and also happens in a given patch ID's subsequent blocks.

#### Behavior When Replaying With Marker After Current Location

If the Event History's Marker Event is after the current execution point, that means the new patch is too early.
The execution will encounter the new patch before the original.
The execution will attempt to write the marker to the replay event history, but it will throw a non-deterministic exception because the replay and original event histories don't match.

#### Behavior When Replaying With No Marker For that Patch ID

During a Replay, if there is no marker for a given patch ID, the execution will return `false` and will not add a marker to the event history. In addition, all future calls to `patched()` with that ID will return `false` -- even after it is done replaying and is running new code.

The [preceding section](#behavior-when-not-replaying) states that if the execution is not replaying, the `patched()` function will always return `true`.
If the marker doesn't exist, it will be added, and if the marker already exists, it won't be re-added.

However, this behavior doesn't occur if there was already a call to `patched()` with that ID in the replay code, but not in the event history.
In this situation, the function won't return `true`.

#### A Summary of the Two Potentially Unexpected Behaviors

Recapping the potentially unexpected behaviors that may occur during a Replay:

If the execution hits a call to `patched()`, but that patch ID isn't _at or before that point_ in the event history, you may not realize that the event history _after_ the current execution location matters.
This behavior occurs because:

- If that patch ID exists later, you get a non-determinism error
- If the patch doesn't exist later, you don't get a non-determinism error, and the call returns `false`

If the execution hits a call to `patched()` with an ID that doesn't exist in the history, then not only will it return `false` in that occurence, but it will also return `false` if the execution surpasses the Replay threshold and is running new code.

#### Implications of the Behaviors

If you deploy new code while Workflows are executing, any Workflows that were in the middle of executing will Replay up to the point they were at when the Worker was shut down.
When they do this Replay, they will not follow the `patched()` branches in the code.
For the rest of the execution after they have replayed to the point before the deployment and worker restart, they will either:

- Use new code if there was no call to `patched()` in the replay code
- If there was a call to `patched()` in the replay code, they will
  run the non-patched code during and after replay

This might sound odd, but it's actually exactly what's needed because that means that if the future patched code depends on earlier patched code, then it won't use the new code -- it will use the old code instead.

But if there's new code in the future, and there was no code earlier in the body that required the new patch, then it can switch over to the new code, which it will do.

Note that this behavior means that the Workflow _does not always run the newest code_.
It only does that if not replaying or if replay is surpassed and there hasn't been a call to `patched()` (with that ID) throughout the replay.

#### Recommendations

Based on this behavior and the implications, when patching in new code, always put the newest code at the top of an if-patched-block.

```python
if patched('v3'):
    # This is the newest version of the code.
    # put this at the top, so when it is running
    # a fresh execution and not replaying,
    # this patched statement will return true
    # and it will run the new code.
    pass
elif patched('v2'):
    pass
else:
    pass
```

The following sample shows how `patched()` will behave in a conditional block that's arranged differently.
In this case, the code's conditional block doesn't have the newest code at the top.
Because `patched()` will return `True` when not Replaying (except with the preceding caveats), this snippet will run the `v2` branch instead of `v3` in new executions.

```python
if patched('v2'):
    # This is bad because when doing a new execution (i.e. not replaying),
    # patched statements evaluate to True (and put a marker
    # in the event history), which means that new executions
    # will use v2, and miss v3 below
    pass
elif patched('v3'):
    pass
else:
  pass
```

---

## Schedule

This page discusses [Schedule](#schedule).

## What is a Schedule? {#schedule}

A Schedule contains instructions for starting a [Workflow Execution](/workflow-execution) at specific times.
Schedules provide a more flexible and user-friendly approach than [Temporal Cron Jobs](/cron-job).

- [How to enable Schedules](#limitations)
- [How to operate Schedules using the Temporal CLI](/cli/schedule)

A Schedule has an identity and is independent of a Workflow Execution.
This differs from a Temporal Cron Job, which relies on a cron schedule as a property of the Workflow Execution.

:::info

For triggering a Workflow Execution at a specific one-time future point rather than on a recurring schedule, the [Start Delay](/workflow-execution/timers-delays#delay-workflow-execution) option should be used instead of a Schedule.

:::

### Action

The Action of a Schedule is where the Workflow Execution properties are established, such as Workflow Type, Task Queue, parameters, and timeouts.

Workflow Executions started by a Schedule have the following additional properties:

- The Action's timestamp is appended to the Workflow Id.
- The `TemporalScheduledStartTime` [Search Attribute](/search-attribute) is added to the Workflow Execution.
  The value is the Action's timestamp.
- The `TemporalScheduledById` Search Attribute is added to the Workflow Execution.
  The value is the Schedule Id.

### Spec

The Schedule Spec defines when the Action should be taken.
Unless many Schedules have Actions scheduled at the same time, Actions should generally start within 1 second of the specified time.
There are two kinds of Schedule Spec:

- A simple interval, like "every 30 minutes" (aligned to start at the Unix epoch, and optionally including a phase offset).
- A calendar-based expression, similar to the "cron expressions" supported by lots of software, including the older Temporal Cron feature.

These two kinds have multiple representations, depending on the interface or SDK you're using, but they all support the same features.

In the Temporal CLI, for example, 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.

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:

```json
{
  "year": "2022",
  "month": "Jan,Apr,Jul,Oct",
  "dayOfMonth": "1,15",
  "hour": "11-14"
}
```

The following calendar JSON fields are available:

- `year`
- `month`
- `dayOfMonth`
- `dayOfWeek`
- `hour`
- `minute`
- `second`
- `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 `*`, so you can describe many useful specs with only a few fields.

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, useful for complicated specs.

No matter which form you supply, calendar and interval specs are converted to canonical representations.
What you see when you "describe" or "list" a Schedule might not look exactly like what you entered, but it has the same meaning.

Other Spec features:

**Multiple intervals/calendar expressions:** A Spec can have combinations of multiple intervals and/or calendar expressions to define a specific Schedule.

**Time bounds:** Provide 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.

**Exclusions:** A Spec can contain exclusions in the form of zero or more calendar expressions.
This can be used to express scheduling like "each Monday at noon except for holidays".
You'll have to provide your own set of exclusions and include it in each schedule; there are no pre-defined sets.
(This feature isn't currently exposed in the Temporal CLI or the Temporal Web UI.)

**Jitter:** 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).

**Time zones:** 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.
(Note: this isn't currently exposed in the Temporal CLI or the web UI.)

### Pause

A Schedule can be Paused.
When a Schedule is Paused, the Spec has no effect.
However, you can still force manual actions by using the [temporal schedule trigger](/cli/schedule#trigger) command.

To assist communication among developers and operators, a “notes” field can be updated on pause or resume to store an explanation for the current state.

### Backfill

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](#overlap-policy) is used; sequentially if `BufferAll` is used).
You might use this 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.

### Limit number of Actions

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.

### Policies

A Schedule supports a set of Policies that enable customizing behavior.

#### Overlap Policy

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 following options are available:

- `Skip`: **Default**.
  Nothing happens; the Workflow Execution is not started.
- `BufferOne`: Starts the Workflow Execution as soon as the current one completes.
  The buffer is limited to one.
  If another Workflow Execution is supposed to start, but one is already in the buffer, only the one in the buffer eventually starts.
- `BufferAll`: Allows an unlimited number of Workflows to buffer.
  They are started sequentially.
- `CancelOther`: Cancels the running Workflow Execution, and then starts the new one after the old one completes cancellation.
- `TerminateOther`: Terminates the running Workflow Execution and starts the new one immediately.
- `AllowAll` Starts any number of concurrent Workflow Executions.
  With this policy (and only this policy), more than one Workflow Execution, started by the Schedule, can run simultaneously.

#### Catchup Window

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.
(But you can always [Backfill](#backfill).)

#### Pause-on-failure

If this 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.

Note that 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.

### Last completion result

A Workflow started by a Schedule can obtain the completion result from the most recent successful run.
(How you do this depends on the SDK you're using.)

For overlap policies that don't allow overlap, “the most recent successful run” is straightforward to define.
For the `AllowAll` policy, it refers to the run that completed most recently, at the time that the run in question is started.
Consider the following overlapping runs:

```
time -------------------------------------------->
 A     |----------------------|
 B               |-------|
 C                          |---------------|
 D                                |--------------T
```

If D asks for the last completion result at time T, it gets the result of A.
Not B, even though B started more recently, because A completed later.
And not C, even though C completed after A, because the result for D is captured when D is started, not when it's queried.

Failures and timeouts do not affect the last completion result.

:::note

When a Schedule triggers a Workflow that completes successfully and yields a result, the result from the initial Schedule execution can be accessed by the subsequent scheduled execution through `LastCompletionResult`.

Be aware that if, during the subsequent run, the Workflow employs the [Continue-As-New](/workflow-execution/continue-as-new) feature, `LastCompletionResult` won't be accessible for this new Workflow iteration.

It is important to note that the [status](/workflow-execution#workflow-execution-status) of the subsequent run is marked as `Continued-As-New` and not as `Completed`.

:::

:::caution

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.
So, for example, a Workflow Execution that returns a result of size 2,096,640 bytes (which is above 2MiB - 1KiB limit)
will be allowed to compete successfully, but that value will not be available as a last completion result.
This limitation may be lifted in the future.

:::

### Last failure

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.

### Limitations

Internally, a Schedule is implemented as a Workflow.
If you're using Advanced Visibility (Elasticsearch), these Workflow Executions are hidden from normal views.
If you're using Standard Visibility, they are visible, though there's no need to interact with them directly.

---

## Temporal Workflow Definition

This pages covers the following:

- [What is a Workflow Definition?](/workflow-definition)
- [Determinism and constraints](#deterministic-constraints)
- [Handling code changes and non-deterministic behavior](#non-deterministic-change)
- [Intrinsic non-determinism logic](#intrinsic-nondeterministic-logic)
- [Versioning Workflow code and Patching](#workflow-versioning)
- [Handling unreliable Worker Processes](#unreliable-worker-processes)
- [What is a Workflow Type?](#workflow-type)

A Temporal Workflow defines the overall flow of the application.
Conceptually, a Workflow is a sequence of steps written in a general-purpose programming language.
With Temporal, those steps are defined by writing code, known as a Workflow Definition, and are carried out by running that code, which results in a Workflow Execution.

In day-to-day conversations, the term _Workflow_ might refer to [Workflow Type](#workflow-type), a [Workflow Definition](/workflow-definition), or a [Workflow Execution](/workflow-execution).
Temporal documentation aims to be explicit and differentiate between them.

## What is a Workflow Definition? {#workflow-definition}

A Workflow Definition is the code that defines the Workflow.
It is written with a programming language and corresponding Temporal SDK.
Depending on the programming language, it's typically implemented as a function or an object method and encompasses the end-to-end series of steps of a Temporal application.

Below are different ways to develop a basic Workflow Definition.

<Tabs groupId="basic-workflow-definition" queryString>
<TabItem value="go" label="Go">

**[Workflow Definition in Go](/develop/go/core-application#develop-workflows)**

```go
func YourBasicWorkflow(ctx workflow.Context) error {
    // ...
    return nil
}
```

</TabItem>
<TabItem value="java" label="Java">

**[Workflow Definition in Java (Interface)](/develop/java/core-application#develop-workflows)**

```java
// Workflow interface
@WorkflowInterface
public interface YourBasicWorkflow {

    @WorkflowMethod
    String workflowMethod(Arguments args);
}
```

**[Workflow Definition in Java (Implementation)](/develop/java/core-application#develop-workflows)**

```java
// Workflow implementation
public class YourBasicWorkflowImpl implements YourBasicWorkflow {
    // ...
}
```

</TabItem>
<TabItem value="php" label="PHP">

**[Workflow Definition in PHP (Interface)](/develop/php/core-application#develop-workflows)**

```php
#[WorkflowInterface]
interface YourBasicWorkflow {
    #[WorkflowMethod]
    public function workflowMethod(Arguments args);
}
```

**[Workflow Definition in PHP (Implementation)](/develop/php/core-application#develop-workflows)**

```php
class YourBasicWorkflowImpl implements YourBasicWorkflow {
    // ...
}
```

</TabItem>
<TabItem value="python" label="Python">

**[Workflow Definition in Python](/develop/python/core-application#develop-workflows)**

```Python
@workflow.defn
class YourWorkflow:
    @workflow.run
    async def YourBasicWorkflow(self, input: str) -> str:
        # ...
```

</TabItem>
<TabItem value="typescript" label="Typescript">

**[Workflow Definition in Typescript](/develop/typescript/core-application#develop-workflows)**

```Typescript
type BasicWorkflowArgs = {
  param: string;
};

export async function WorkflowExample(
  args: BasicWorkflowArgs,
): Promise<{ result: string }> {
  // ...
}
```

</TabItem>
<TabItem value="dotnet" label=".NET">

**[Workflow Definition in C# and .NET](/develop/dotnet/core-application#develop-workflow)**

```csharp
[Workflow]
public class YourBasicWorkflow {

    [WorkflowRun]
    public async Task<string> workflowExample(string param) {
        // ...
    }
}
```

</TabItem>

</Tabs>

A Workflow Definition may be also referred to as a Workflow Function.
In Temporal's documentation, a Workflow Definition refers to the source for the instance of a Workflow Execution, while a Workflow Function refers to the source for the instance of a Workflow Function Execution.

A Workflow Execution effectively executes once to completion, while a Workflow Function Execution occurs many times during the life of a Workflow Execution.

We strongly recommend that you write a Workflow Definition in a language that has a corresponding Temporal SDK.

### Deterministic constraints {#deterministic-constraints}

A critical aspect of developing Workflow Definitions is ensuring that they are deterministic.
Generally speaking, this means you must take care to ensure that any time your Workflow code is executed it makes the same Workflow API calls in the same sequence, given the same input.
Some changes to those API calls are safe to make.

For example, you can change:

- The input parameters, return values, and execution timeouts of Child Workflows and Activities
  - However, it is not safe to change the types or IDs of Child Workflows or Activities
- The input parameters used to Signal an external Workflow
- The duration of Timers (although changing them to 0 is not safe in all SDKs)
- Add or remove calls to Workflow APIs that don't produce [Commands](/workflow-execution#command) (For example - `workflow.GetInfo` in the Go SDK or its equivalent in other SDKs)

The following Workflow API calls all can produce Commands, and thus must not be reordered, added, or removed without proper [Versioning techniques](#workflow-versioning):

- Starting or cancelling a Timer
- Scheduling or cancelling Activity Executions (including local Activities)
- Starting or cancelling Child Workflow executions
- Signalling or cancelling signals to external Workflow Executions
- Scheduling or cancelling Nexus operations
- Ending the Workflow Execution in any way (completing, failing, cancelling, or continuing-as-new)
- `Patched` or `GetVersion` calls for Versioning (although they may be added or removed according to the [patching](#workflow-patching) rules)
- Upserting Workflow Search Attributes
- Upserting Workflow Memos
- Running a `SideEffect` or `MutableSideEffect`

For a complete reference, see the [Command reference](/references/commands).

More formally, the use of certain Workflow APIs in the function is what generates Commands.
Commands tell the Temporal Service which Events to create and add to the Workflow Execution's [Event History](/workflow-execution/event#event-history).
When the Workflow's code [replays](/workflow-execution#replay), the Commands that are emitted are compared with the existing Event History.
If a corresponding Event already exists within the Event History that matches that command, then the Execution progresses.
See [Event History](/encyclopedia/event-history/) for a detailed walkthrough of the process.

For example, using an SDK's "Execute Activity" API generates the [ScheduleActivityTask](/references/commands#scheduleactivitytask) Command.
When this API is called upon re-execution, that Command is compared with the Event that is in the same location within the sequence.
The Event in the sequence must be an [ActivityTaskScheduled](/references/events#activitytaskscheduled) Event, where the Activity name is the same as what is in the Command.

If a generated Command doesn't match what it needs to in the existing Event History, then the Workflow Execution returns a _non-deterministic_ error.

The following are the two reasons why a Command might be generated out of sequence or the wrong Command might be generated altogether:

1. Code changes are made to a Workflow Definition that is in use by a running Workflow Execution.
2. There is intrinsic non-deterministic logic (such as inline random branching).

### Code changes can cause non-deterministic behavior {#non-deterministic-change}

The Workflow Definition can change in very limited ways once there is a Workflow Execution depending on it.
To alleviate non-deterministic issues that arise from code changes, we recommend using [Workflow Versioning](#workflow-versioning).

For example, let's say we have a Workflow Definition that defines the following sequence:

1. Start and wait on a Timer/sleep.
2. Spawn and wait on an Activity Execution.
3. Complete.

We start a Worker and spawn a Workflow Execution that uses that Workflow Definition.
The Worker would emit the [StartTimer](/references/commands#starttimer) Command and the Workflow Execution would become suspended.

Before the Timer is up, we change the Workflow Definition to the following sequence:

1. Spawn and wait on an Activity Execution.
2. Start and wait on a Timer/sleep.
3. Complete.

When the Timer fires, the next Workflow Task will cause the Workflow Function to re-execute.
The first Command the Worker sees would be ScheduleActivityTask Command, which wouldn't match up to the expected [TimerStarted](/references/events#timerstarted) Event.

The Workflow Execution would fail and return a nondeterminism error.

The following are examples of minor changes that would not result in non-determinism errors when re-executing a History which already contain the Events:

- Changing the duration of a Timer, with the following exceptions:
  - In Java, Python, and Go, changing a Timer's duration from or to 0 is a non-deterministic behavior.
  - In .NET, changing a Timer's duration from or to -1 (which means "infinite") is a non-deterministic behavior.
- Changing the arguments to:
  - The Activity Options in a call to spawn an Activity Execution (local or nonlocal).
  - The Child Workflow Options in a call to spawn a Child Workflow Execution.
  - Call to Signal an External Workflow Execution.
- Adding a Signal Handler for a Signal Type that has not been sent to this Workflow Execution.

### Intrinsic non-deterministic logic {#intrinsic-nondeterministic-logic}

Intrinsic non-determinism is when a Workflow Function Execution might emit a different sequence of Commands on re-execution, regardless of whether all the input parameters are the same.

For example, a Workflow Definition can not have inline logic that branches (emits a different Command sequence) based off a local time setting or a random number.
In the representative pseudocode below, the `local_clock()` function returns the local time, rather than Temporal-defined time:

```text
fn your_workflow() {
  if local_clock().is_before("12pm") {
    await workflow.sleep(duration_until("12pm"))
  } else {
    await your_afternoon_activity()
  }
}
```

Each Temporal SDK offers APIs that enable Workflow Definitions to have logic that gets and uses time, random numbers, and data from unreliable resources.
When those APIs are used, the results are stored as part of the Event History, which means that a re-executed Workflow Function will issue the same sequence of Commands, even if there is branching involved.

In other words, all operations that do not purely mutate the Workflow Execution's state should occur through a Temporal SDK API.

### Versioning Workflows {#workflow-versioning}

The Temporal Platform requires that Workflow code (Workflow Definitions) be deterministic in nature.
This requirement means that developers should consider how they plan to handle changes to Workflow code over time.

A versioning strategy is even more important if your Workflow Executions live long enough to run on multiple versions of your Worker. Temporal Platform provides Workflow Versioning APIs.

Temporal offers two Versioning strategies:

- [Worker Versioning](#worker-versioning): keep Workers tied to specific code revisions, so that old Workers can run old code paths and new Workers can run new code paths.

:::note
Support for the experimental method of Worker Versioning prior to 2025 will be removed from Temporal Server in March 2026. Refer to the [latest Worker Versioning docs](/worker-versioning) for guidance.
:::

- [Versioning with patching](#workflow-patching): make sure your code changes are compatible across versions of your Workflow.

You can use either strategy, or a combination.

#### Worker Versioning {#worker-versioning}

This is the **recommended** way to handle versioning and users see improved error rates when adopting it. To learn more about Worker Versioning, see our [Worker Versioning in production](production-deployment/worker-deployments/worker-versioning) page.

#### Versioning with Patching {#workflow-patching}

When keeping Workflows compatible, you should patch and ideally how to test your running Workflows will be safe to run on a new code version.

To patch:

- [How to patch Workflow code in Go](/develop/go/versioning#patching)
- [How to patch Workflow code in Java](/develop/java/versioning#patching)
- [How to patch Workflow code in Python](/develop/python/versioning#patching)
- [How to patch Workflow code in PHP](/develop/php/versioning#php-sdk-patching-api)
- [How to patch Workflow code in TypeScript](/develop/typescript/versioning#patching)
- [How to patch Workflow code in .NET](/develop/dotnet/versioning#patching)

To test, see [Safe Deployments](/develop/safe-deployments.mdx).

### Handling unreliable Worker Processes {#unreliable-worker-processes}

You do not handle Worker Process failure or restarts in a Workflow Definition.

Workflow Function Executions are completely oblivious to the Worker Process in terms of failures or downtime.
The Temporal Platform ensures that the state of a Workflow Execution is recovered and progress resumes if there is an outage of either Worker Processes or the Temporal Service itself.
The only reason a Workflow Execution might fail is due to the code throwing an error or exception, not because of underlying infrastructure outages.

### What is a Workflow Type? {#workflow-type}

A Workflow Type is a name that maps to a Workflow Definition.

- A single Workflow Type can be instantiated as multiple Workflow Executions.
- A Workflow Type is scoped by a Task Queue.
  It is acceptable to have the same Workflow Type name map to different Workflow Definitions if they are using completely different Workers.

<CaptionedImage
    src="/diagrams/workflow-type-cardinality.svg"
    title="Workflow Type cardinality with Workflow Definitions and Workflow Executions" />

---

## Continue-As-New

This page discusses [Continue-As-New](#continue-as-new) and how to decide [when to use it](#when).

## What is Continue-As-New? {#continue-as-new}

Continue-As-New allows you to checkpoint your Workflow's state and start a fresh Workflow.

There are two main reasons you might want to start a new Workflow:

- A Workflow Execution with a long, or large [Event History](/workflow-execution/event#event-history), such as one calling many Activities, may bog down and have performance issues.
  It could even generate more Events than allowed by the [Event History limits](/workflow-execution/event#event-history-limits).
- A Workflow Execution can hit [Workflow Versioning](/workflow-definition#workflow-versioning) problems if it started running on an older version of your code and then begins executing on a newer version.

Your goal is to create a new Workflow with a fresh history that picks up where your last one left off.
First, pass your latest relevant state into Continue-As-New.
This hands it to a new Execution in the [Execution Chain](/workflow-execution#workflow-execution-chain).
This state is passed in as arguments to your Workflow.
The parameters are typically optional and left unset by the original caller of the Workflow.

The new Workflow Execution has the same Workflow Id, but a different Run Id, and starts its own Event History.

You can repeat Continue-As-New as often as needed, which means that your Workflow can run forever.
Workflows that do this are often called Entity Workflows because they represent durable objects, not just processes.

- [How to Continue-As-New using the Go SDK](/develop/go/continue-as-new#how)
- [How to Continue-As-New using the Java SDK](/develop/java/continue-as-new)
- [How to Continue-As-New using the PHP SDK](/develop/php/continue-as-new)
- [How to Continue-As-New using the Python SDK](/develop/python/continue-as-new#how)
- [How to Continue-As-New using the TypeScript SDK](/develop/typescript/continue-as-new)
- [How to Continue-As-New using the .NET SDK](/develop/dotnet/continue-as-new)

## When in your Workflow is it right to Continue-As-New? {#when}

Temporal will tell your Workflow when it's approaching performance or scalability problems.
Find out if it's time by checking Continue-As-New Suggested in your Workflow at spots in your implementation where you are ready to checkpoint your state.

To prevent long-running Workflows from running on stale versions of code, you may also want to Continue-as-New periodically, depending on how often you deploy. This makes sure you're running only a couple of versions, which avoids some backwards compatibility problems.

- [Determine when to Continue-As-New using the Go SDK](/develop/go/continue-as-new#when)
- [Determine when to Continue-As-New using the Java SDK](/develop/java/continue-as-new)
- [Determine when to Continue-As-New using the PHP SDK](/develop/php/continue-as-new)
- [Determine when to Continue-As-New using the Python SDK](/develop/python/continue-as-new#when)
- [Determine when to Continue-As-New using the TypeScript SDK](/develop/typescript/continue-as-new)
- [Determine when to Continue-As-New using the .NET SDK](/develop/dotnet/continue-as-new)

---

## Events and Event History

This page discusses the following:

- [Events](#event)
- [Activity Events](#activity-events)
- [Event History](#event-history)
- [Event Loop](#event-loop)
- [Time Constraints](#time-constraints)
- [Reset](#reset)
- [Side Effect](#side-effect)

The Temporal Service tracks the progress of each Workflow Execution by appending information about Events, such as when the Workflow Execution began or ended, to the Event History associated with that execution.
This information not only enables developers to know what took place, but is also essential for providing Durable Execution, since it enables the Workflow Execution to recover from a crash and continue making progress.
In order to maintain high performance, the Temporal Service places limits on both the number and size of items in the Event History for each Workflow Execution.

## What is an Event? {#event}

Events are created by the Temporal Service in response to external occurrences and Commands generated by a Workflow Execution.
Each Event corresponds to an `enum` that is defined in the [Server API](https://github.com/temporalio/api/blob/master/temporal/api/enums/v1/event_type.proto).

All Events are recorded in the [Event History](#event-history).

A list of all possible Events that could appear in a Workflow Execution Event History is provided in the [Event reference](/references/events).

### Activity Events {#activity-events}

Seven Activity-related Events are added to Event History at various points in an Activity Execution:

- After a [Workflow Task Execution](/tasks#activity-task-execution) reaches a line of code that starts/executes an Activity, the Worker sends the Activity Type and arguments to the Temporal Service, and the Temporal Service adds an [ActivityTaskScheduled](/references/events#activitytaskscheduled) Event to Event History.
- When `ActivityTaskScheduled` is added to History, the Temporal Service adds a corresponding Activity Task to the Task Queue.
- A Worker polling that Task Queue picks up the Activity Task and runs the Activity function or method.
- If the Activity function returns, the Worker reports completion to the Temporal Service, and the Temporal Service adds [ActivityTaskStarted](/references/events#activitytaskstarted) and [ActivityTaskCompleted](/references/events#activitytaskcompleted) to Event History.
- If the Activity function throws a [non-retryable Failure](/references/failures#non-retryable), the Temporal Service adds [ActivityTaskStarted](/references/events#activitytaskstarted) and [ActivityTaskFailed](/references/events#activitytaskfailed) to Event History.
- If the Activity function throws an error or retryable Failure, the Temporal Service schedules an Activity Task retry to be added to the Task Queue (unless you’ve reached the Maximum Attempts value of the [Retry Policy](/encyclopedia/retry-policies), in which case the Temporal Service adds [ActivityTaskStarted](/references/events#activitytaskstarted) and [ActivityTaskFailed](/references/events#activitytaskfailed) to Event History).
- If the Activity’s [Start-to-Close Timeout](/encyclopedia/detecting-activity-failures#start-to-close-timeout) passes before the Activity function returns or throws, the Temporal Service schedules a retry.
- If the Activity’s [Schedule-to-Close Timeout](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout) passes before Activity Execution is complete, or if [Schedule-to-Start Timeout](/encyclopedia/detecting-activity-failures#schedule-to-start-timeout) passes before a Worker gets the Activity Task, the Temporal Service writes [ActivityTaskTimedOut](/references/events#activitytasktimedout) to Event History.
- If the Activity is [canceled](/activity-execution#cancellation), the Temporal Service writes [ActivityTaskCancelRequested](/references/events#activitytaskcancelrequested) to Event History, and if the Activity accepts cancellation, the Temporal Service writes [ActivityTaskCanceled](/references/events#activitytaskcanceled).

:::note

While the Activity is running and retrying, [ActivityTaskScheduled](/references/events#activitytaskscheduled) is the only Activity-related Event in History: [ActivityTaskStarted](/references/events#activitytaskstarted) is written along with a terminal Event like [ActivityTaskCompleted](/references/events#activitytaskcompleted) or [ActivityTaskFailed](/references/events#activitytaskfailed).

:::

### What is an Event History? {#event-history}

An append-only log of [Events](#event) for your application.

- Event History is durably persisted by the Temporal service, enabling seamless recovery of your application state from crashes or failures.
- It also serves as an audit log for debugging.

### Event History limits {#event-history-limits}

The Temporal Service stores the complete Event History for the entire lifecycle of a Workflow Execution.

The Temporal Service logs a [warning after 10,240 Events](/workflow-execution/limits) and periodically logs additional warnings as new Events are added.

The Workflow Execution is terminated when the Event History:

- exceeds 51,200 Events.
- contains more than 2000 Updates.
- contains more than 10000 Signals.

To avoid hitting these limits, you can use the [Continue-As-New](/workflow-execution/continue-as-new) feature to close the current Workflow Execution and create a new one.

### Event loop {#event-loop}

A Workflow Execution is made up of a sequence of [Events](#event) called an [Event History](#event-history).
Events are created by the Temporal Service in response to either Commands or actions requested by a Temporal Client (such as a request to spawn a Workflow Execution).

<CaptionedImage
    src="/diagrams/workflow-execution-swim-lane-01.svg"
    title="Workflow Execution" />

## Time constraints {#time-constraints}

**Is there a limit to how long Workflows can run?**

No, there is no time constraint on how long a Workflow Execution can run.

However, if your Workflow will perform many actions, or will receive many messages, it can run into [Event History limits](#event-history-limits).

It can also hit [Workflow Versioning](/workflow-definition#workflow-versioning) and other backwards incompatibility problems.

For these reasons, it can be a good idea to [Continue-As-New](/workflow-execution/continue-as-new) periodically.

## What is a Reset? {#reset}

A Reset terminates a [Workflow Execution](/workflow-execution) and creates a new Workflow Execution with the same [Workflow Type](/workflow-definition#workflow-type) and [Workflow ID](/workflow-execution/workflowid-runid).
The [Event History](/workflow-execution/event#event-history) is copied from the original execution up to and including the reset point.
The new execution continues from the reset point. Valid reset points are: `WorkflowTaskStarted`, `WorkflowTaskCompleted`, `WorkflowTaskTimedOut`, and `WorkflowTaskFailed`.
Signals in the original history can be optionally copied to the new history, whether they appear after the reset point or not.

## What is a Side Effect? {#side-effect}

:::note

Side Effects are included in the Go, Java, and PHP SDKs.
They are not included in other SDKs.
[Local Activities](/local-activity) fit the same use case and are slightly less resource intensive.

:::

A Side Effect is a way to execute a short, non-deterministic code snippet, such as generating a UUID, that executes the provided function once and records its result into the Workflow Execution Event History.

A Side Effect does not re-execute upon replay, but instead returns the recorded result.

Do not ever have a Side Effect that could fail, because failure could result in the Side Effect function executing more than once.
If there is any chance that the code provided to the Side Effect could fail, use an Activity.

---

## Workflow Execution Limits

This page discusses [Workflow Execution limits](#workflow-execution-limits), [Workflow Execution Callback limits](#workflow-execution-callback-limits), and [Nexus Operation limits](#workflow-execution-nexus-operation-limits).

## Limits {#workflow-execution-limits}

There is no limit to the number of concurrent Workflow Executions, albeit you must abide by the Workflow Execution's Event History limit.

:::caution

As a precautionary measure, the Workflow Execution's Event History is limited to [51,200 Events](https://github.com/temporalio/temporal/blob/e3496b1c51bfaaae8142b78e4032cc791de8a76f/service/history/configs/config.go#L382) or [50 MB](https://github.com/temporalio/temporal/blob/e3496b1c51bfaaae8142b78e4032cc791de8a76f/service/history/configs/config.go#L380) and will warn you after 10,240 Events or 10 MB.

:::

There is also a limit to the number of certain types of incomplete operations.

Each in-progress Activity generates a metadata entry in the Workflow Execution's mutable state.
Too many entries in a single Workflow Execution's mutable state causes unstable persistence.
To protect the system, Temporal enforces a maximum number of incomplete Activities, Child Workflows, Signals, or Cancellation requests per Workflow Execution (by default, 2,000 for each type of operation).
Once the limit is reached for a type of operation, if the Workflow Execution attempts to start another operation of that type (by producing a `ScheduleActivityTask`, `StartChildWorkflowExecution`, `SignalExternalWorkflowExecution`, or `RequestCancelExternalWorkflowExecution` Command), it will be unable to (the Workflow Task Execution will fail and get retried).

These limits are set with the following [dynamic configuration keys](https://github.com/temporalio/temporal/blob/main/service/history/configs/config.go):

- `NumPendingActivitiesLimit`
- `NumPendingChildExecutionsLimit`
- `NumPendingSignalsLimit`
- `NumPendingCancelRequestsLimit`

## Workflow Execution Callback limits {#workflow-execution-callback-limits}

There is a limit to the total number of Workflow Callbacks that may be attached to a single Workflow Execution (by default, 32 Workflow Callbacks).
Attaching [multiple Nexus callers to a handler Workflow](/nexus/operations#attaching-multiple-nexus-callers) may exceed these limits.

These limits can be set with the following [dynamic configuration keys](https://github.com/temporalio/temporal/blob/main/common/dynamicconfig/constants.go#L924):

- MaxCallbacksPerWorkflow

## Workflow Execution Nexus Operation Limits {#workflow-execution-nexus-operation-limits}

There is a limit to the maximum number of Nexus Operations in a Workflow before Continue-As-New is required.
Each in-progress Nexus Operation generates a metadata entry in the Workflow Execution's mutable state.
Too many entries in a single Workflow Execution's mutable state causes unstable persistence.
To protect the system, Temporal enforces a maximum number of incomplete Nexus Operation requests per Workflow Execution (by default, 30 Nexus Operations).
Once the limit is reached for a type of operation, if the Workflow Execution attempts to start another Nexus operation (by producing a ScheduleNexusOperation), it will be unable to do so (the Workflow Task Execution will fail and get retried).

These limits are set with the following [dynamic configuration keys](https://github.com/temporalio/temporal/blob/de7c8879e103be666a7b067cc1b247f0ac63c25c/components/nexusoperations/config.go#L38):

- MaxConcurrentOperations

---

## Timers and Start Delays

This page discusses [Timer](#timer) and [Start Delay](#delay-workflow-execution).

## What is a Timer? {#timer}

Temporal SDKs offer Timer APIs so that Workflow Executions are deterministic in their handling of time values.

Timers in Temporal are persisted, meaning that even if your Worker or Temporal Service is down when the time period completes, as soon as your Worker and Temporal Service become available, the call that is awaiting the Timer in your Workflow code will resolve, causing execution to proceed.
Timers are reliable and efficient.
Workers consume no additional resources while waiting for a Timer to fire, so a single Worker can await millions of Timers concurrently.

- [How to set Timers in Go](/develop/go/timers)
- [How to set Timers in Java](/develop/java/timers)
- [How to set Timers in PHP](/develop/php/timers)
- [How to set Timers in Python](/develop/python/timers)
- [How to set Timers in TypeScript](/develop/typescript/timers)
- [How to set Timers in .NET](/develop/dotnet/durable-timers)

The duration of a Timer is fixed, and your Workflow might specify a value as short as one second or as long as several years.
Although it's possible to specify an extremely precise duration, such as 36 milliseconds or 15.072 minutes, your Workflows should not rely on sub-second accuracy for Timers.
We recommend that you consider the duration as a minimum time, one which will be rounded up slightly due to the latency involved with scheduling and firing the Timer.
For example, setting a Timer for 11.97 seconds is guaranteed to delay execution for at least that long, but will likely be closer to 12 seconds in practice.

## What is a Start Delay? {#delay-workflow-execution}

:::tip COMPATIBILITY

Start Delay Workflow Execution is incompatible with both [Schedules](/schedule) and [Cron Jobs](/cron-job).

:::

Start Delay determines the amount of time to wait before initiating a Workflow Execution.
This is useful if you have a Workflow you want to schedule out in the future, but only want it to execute once: in comparison to reoccurring Workflows using Schedules.

If the Workflow receives a Signal-With-Start or Update-With-Start during the delay, it dispatches a Workflow Task and the remaining delay is bypassed.
If the Workflow receives a Signal during the delay that is not a Signal-With-Start, the Signal does not interrupt the delay, and the Workflow continues to be delayed until the delay expires or a Signal-With-Start is received.

You can delay the dispatch of the initial Workflow Execution by setting this option in the Workflow Options field of your chosen SDK.
This delay only applies to the initial Workflow Execution and does not affect subsequent executions, such as when the Workflow Continues-as-New.

---

## Temporal Workflow Execution Overview

This page provides an overview of Workflow Execution:

- [What is a Workflow Execution?](#workflow-execution)
- [Replay](#replay)
- [Commands and awaitables](#commands-awaitables)
- [What is a Command?](#command)
- [Checking Workflow Execution Status](#workflow-execution-status)
- [Workflow Execution Chain](#workflow-execution-chain)
- [Memo](#memo)
- [State Transition](#state-transition)

## What is a Workflow Execution? {#workflow-execution}

While the Workflow Definition is the code that defines the Workflow, the Workflow Execution is created by executing that code.
A Temporal Workflow Execution is a durable, reliable, and scalable function execution.
It is the main unit of execution of a [Temporal Application](/temporal#temporal-application).

- [How to start a Workflow Execution using temporal](/cli/workflow#start)
- [How to start a Workflow Execution using the Go SDK](/develop/go/temporal-client#start-workflow-execution)
- [How to start a Workflow Execution using the Java SDK](/develop/java/temporal-client#start-workflow-execution)
- [How to start a Workflow Execution using the PHP SDK](/develop/php/temporal-client#start-workflow-execution)
- [How to start a Workflow Execution using the Python SDK](/develop/python/temporal-client#start-workflow-execution)
- [How to start a Workflow Execution using the TypeScript SDK](/develop/typescript/temporal-client#start-workflow-execution)
- [How to start a Workflow Execution using the .NET SDK](/develop/dotnet/temporal-client#start-workflow)

Each Temporal Workflow Execution has exclusive access to its local state.
It executes concurrently to all other Workflow Executions, and communicates with other Workflow Executions through [Signals](/sending-messages#sending-signals) and the environment through [Activities](/activities).
While a single Workflow Execution has limits on size and throughput, a Temporal Application can consist of millions to billions of Workflow Executions.

**Durability**

Durability is the absence of an imposed time limit.

A Workflow Execution is durable because it executes a Temporal Workflow Definition (also called a Temporal Workflow Function), your application code, effectively once and to completion—whether your code executes for seconds or years.

**Reliability**

Reliability is responsiveness in the presence of failure.

A Workflow Execution is reliable, because it is fully recoverable after a failure.
The Temporal Platform ensures the state of the Workflow Execution persists in the face of failures and outages and resumes execution from the latest state.

**Scalability**

Scalability is responsiveness in the presence of load.

A single Workflow Execution is limited in size and throughput but is scalable because it can [Continue-As-New](/workflow-execution/continue-as-new) in response to load.
A Temporal Application is scalable because the Temporal Platform is capable of supporting millions to billions of Workflow Executions executing concurrently, which is realized by the design and nature of the [Temporal Service](/temporal-service) and [Worker Processes](/workers#worker-process).

### Replays {#replay}

A Replay is the method by which a Workflow Execution resumes making progress. During a Replay the Commands that are generated are checked against an existing Event History. Replays are necessary and often happen to give the effect that Workflow Executions are resumable, reliable, and durable.

For more information, see [Deterministic constraints](/workflow-definition#deterministic-constraints).

If a failure occurs, the Workflow Execution picks up where the last recorded event occurred in the Event History.

- [How to use Replay APIs using the Go SDK](/develop/go/testing-suite#replay)
- [How to use Replay APIs using the Java SDK](/develop/java/testing-suite#replay)
- [How to use Replay APIs using the Python SDK](/develop/python/testing-suite#replay)
- [How to use Replay APIs using the TypeScript SDK](/develop/typescript/testing-suite#replay)
- [How to use Replay APIs using the .NET SDK](/develop/dotnet/testing-suite#replay)

### Commands and awaitables {#commands-awaitables}

A Workflow Execution does two things:

1. Issue [Commands](#command).
2. Wait on an Awaitables (often called Futures).

<CaptionedImage
    src="/diagrams/workflow-execution-progession-simple.svg"
    title="Command generation and waiting" />

Commands are issued and Awaitables are provided by the use of Workflow APIs in the [Workflow Definition](/workflow-definition).

Commands are generated whenever the Workflow Function is executed.
The Worker Process supervises the Command generation and makes sure that it maps to the current Event History.
(For more information, see [Deterministic constraints](/workflow-definition#deterministic-constraints).)
The Worker Process batches the Commands and then suspends progress to send the Commands to the Temporal Service whenever the Workflow Function reaches a place where it can no longer progress without a result from an Awaitable.

A Workflow Execution may only ever block progress on an Awaitable that is provided through a Temporal SDK API.
Awaitables are provided when using APIs for the following:

- Awaiting: Progress can block using explicit "Await" APIs.
- Requesting cancellation of another Workflow Execution: Progress can block on confirmation that the other Workflow Execution is cancelled.
- Sending a [Signal](/sending-messages#sending-signals): Progress can block on confirmation that the Signal sent.
- Spawning a [Child Workflow Execution](/child-workflows): Progress can block on confirmation that the Child Workflow Execution started, and on the result of the Child Workflow Execution.
- Spawning an [Activity Execution](/activity-execution): Progress can block on the result of the Activity Execution.
- Starting a Timer: Progress can block until the Timer fires.

### What is a Command? {#command}

A Command is a requested action issued by a [Worker](/workers#worker) to the [Temporal Service](/temporal-service) after a [Workflow Task Execution](/tasks#workflow-task-execution) completes.

The action that the Temporal Service takes is recorded in the [Workflow Execution's](#workflow-execution) [Event History](/workflow-execution/event#event-history) as an [Event](/workflow-execution/event).
The Workflow Execution can await on some of the Events that come as a result from some of the Commands.

Commands are generated by the use of Workflow APIs in your code. During a Workflow Task Execution there may be several Commands that are generated.
The Commands are batched and sent to the Temporal Service as part of the Workflow Task Execution completion request, after the Workflow Task has progressed as far as it can with the Workflow function.
There will always be [WorkflowTaskStarted](/references/events#workflowtaskstarted) and [WorkflowTaskCompleted](/references/events#workflowtaskcompleted) Events in the Event History when there is a Workflow Task Execution completion request.

<CaptionedImage
    src="/diagrams/commands.svg"
    title="Commands are generated by the use of Workflow APIs in your code" />

Commands are described in the [Command reference](/references/commands) and are defined in the [Temporal gRPC API](https://github.com/temporalio/api/blob/master/temporal/api/command/v1/message.proto).

### Status {#workflow-execution-status}

A Workflow Execution can be either _Open_ or _Closed_.

<CaptionedImage
    src="/diagrams/workflow-execution-statuses.svg"
    title="Workflow Execution statuses" />

#### Open

An _Open_ status means that the Workflow Execution is able to make progress.

- Running: The only Open status for a Workflow Execution.
  When the Workflow Execution is Running, it is either actively progressing or is waiting on something.

#### Closed

A _Closed_ status means that the Workflow Execution cannot make further progress because of one of the following reasons:

- Cancelled: The Workflow Execution successfully handled a cancellation request.
- Completed: The Workflow Execution has completed successfully.
- Continued-As-New: The Workflow Execution [Continued-As-New](/workflow-execution/continue-as-new).
- Failed: The Workflow Execution returned an error and failed.
- Terminated: The Workflow Execution was terminated.
- Timed Out: The Workflow Execution reached a timeout limit.

### Workflow Execution Chain {#workflow-execution-chain}

A Workflow Execution Chain is a sequence of Workflow Executions that share the same Workflow Id.
Each link in the Chain is often called a Workflow Run.
Each Workflow Run in the sequence is connected by one of the following:

- [Continue-As-New](/workflow-execution/continue-as-new)
- [Retries](/encyclopedia/retry-policies)
- [Temporal Cron Job](/cron-job)

A Workflow Execution is uniquely identified by its [Namespace](/namespaces), [Workflow Id](/workflow-execution/workflowid-runid#workflow-id), and [Run Id](/workflow-execution/workflowid-runid#run-id).

The [Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout) applies to a Workflow Execution Chain.
The [Workflow Run Timeout](/encyclopedia/detecting-workflow-failures#workflow-run-timeout) applies to a single Workflow Execution (Workflow Run).

## What is a Memo? {#memo}

A Memo is a non-indexed set of Workflow Execution metadata that developers supply at start time or in Workflow code and that is returned when you describe or list Workflow Executions.

The primary purpose of using a Memo is to enhance the organization and management of Workflow Executions.
Add your own metadata, such as notes or descriptions, to a Workflow Execution, which lets you annotate and categorize Workflow Executions based on developer-defined criteria.
This feature is particularly useful when dealing with numerous Workflow Executions because it facilitates the addition of context, reminders, or any other relevant information that aids in understanding or tracking the Workflow Execution.

:::note Use Memos judiciously

Memos shouldn't store data that's critical to the execution of a Workflow, for some of the following reasons:

- Unlike Workflow inputs, Memos lack type safety
- Memos are subject to eventual consistency and may not be immediately available
- Excessive reliance on Memos hides mutable state from the Workflow Execution History

:::

## What is a State Transition? {#state-transition}

A State Transition is a unit of progress made by a [Workflow Execution](#workflow-execution).
Each State Transition is recorded in a persistence store.

Some operations, such as [Activity Heartbeats](/encyclopedia/detecting-activity-failures#activity-heartbeat), require only one or two State Transitions each. With an Activity Heartbeat, there are two: the Activity Heartbeat and a Timer.

Most operations require multiple State Transitions.

For example, a simple Workflow with two sequential [Activity Tasks](/tasks#activity-task) (and no retries) produces 11 State Transitions: two for Workflow start, four for each Activity, and one for Workflow completion.

:::tip NEXT STEPS
For more information on Workflow Execution, please refer to the following subpages:

- [Event](/workflow-execution/event)
- [Workflow Id and Run Id](/workflow-execution/workflowid-runid)
- [Limits](/workflow-execution/limits)
- [Continue-as-New](/workflow-execution/continue-as-new)
- [Timers and Start Delay](/workflow-execution/timers-delays)
  :::

---

## Workflow Id and Run Id

This page discusses the following:

- [Run Id](#run-id)
- [Operations leading to non-determinism](#run-id-non-determinism)
- [Workflow Id](#workflow-id)
- [Workflow Id Reuse Policy](#workflow-id-reuse-policy)
- [Workflow Id Conflict Policy](#workflow-id-conflict-policy)

Each Workflow Execution is associated with a user-defined [Workflow ID](#workflow-id), a value which typically carries some business meaning (such as an order number or customer number).
Temporal guarantees that there can be at most one Workflow Execution with a given ID running at any point in time, a constraint that helps to protect against unexpected duplication.
In some cases, such as when running the same Workflow at recurring intervals using the Schedules features, there can be multiple "runs" of a single Workflow Execution over a period of time.
In this case, all runs will have the same Workflow ID.
However, each run will have a unique system-generated [Run ID](#run-id).

## What is a Run Id? {#run-id}

A Run Id is a globally unique, platform-level identifier for a [Workflow Execution](/workflow-execution).

The current Run Id is mutable and can change during a [Workflow Retry](/encyclopedia/retry-policies). You shouldn't rely on storing the current Run Id, or using it for any logical choices, because a Workflow Retry changes the Run Id and can lead to non-determinism issues.

Temporal guarantees that only one Workflow Execution with a given [Workflow Id](#workflow-id) can be in an Open state at any given time.
But when a Workflow Execution reaches a Closed state, it is possible to have another Workflow Execution in an Open state with the same Workflow Id.
For example, a Temporal Cron Job is a chain of Workflow Executions that all have the same Workflow Id.
Each Workflow Execution within the chain is considered a _Run_.

A Run Id uniquely identifies a Workflow Execution even if it shares a Workflow Id with other Workflow Executions.

### Which operations lead to non-determinism issues?{#run-id-non-determinism}

An operation like `ContinueAsNew`, `Retry`, `Cron`, and `Reset` creates a [Workflow Execution Chain](/workflow-execution#workflow-execution-chain) as identified by the [`first_execution_run_id`](https://github.com/temporalio/api/blob/master/temporal/api/history/v1/message.proto).

Each operation creates a new Workflow Execution inside a chain run and saves its information as `first_execution_run_id`.
Thus, the Run Id is updated during each operation on a Workflow Execution.

- The `first_execution_run_id` is the Run Id of the first Workflow Execution in a Chain run.
- The `original_execution_run_id` is the Run Id when the `WorkflowExecutionStarted` Event occurs.

A Workflow `Reset` changes the first execution Run Id, but preserves the original execution Run Id.
For example, when a new Workflow Execution in the chain starts, it stores its Run Id in `original_execution_run_id`.
A reset doesn't change that field, but the current Run Id is updated.

:::caution

Because of this behavior, you shouldn't rely on the current Run Id in your code to make logical choices.

:::

**Learn more**

For more information, see the following link.

- [`message.proto`](https://github.com/temporalio/api/blob/master/temporal/api/history/v1/message.proto#L75-L82)

## What is a Workflow Id? {#workflow-id}

A Workflow Id is a customizable, application-level identifier for a [Workflow Execution](/workflow-execution) that is unique to an Open Workflow Execution within a [Namespace](/namespaces).

- [How to set a Workflow Id](/develop/go/temporal-client#workflow-id)

A Workflow Id is meant to be a business-process identifier, such as customer identifier or order identifier.

The Temporal Platform guarantees uniqueness of the Workflow Id within a [Namespace](/namespaces) based on the Workflow Id Reuse Policy.

A [Workflow Id Reuse Policy](#workflow-id-reuse-policy) can be used to manage whether a Workflow Id from a Closed Workflow can be re-used.

A [Workflow Id Conflict Policy](#workflow-id-conflict-policy) can be used to decide how to resolve a Workflow Id conflict with a Running Workflow.

A Workflow Execution can be uniquely identified across all Namespaces by its [Namespace](/namespaces), Workflow Id, and [Run Id](#run-id).

### What is a Workflow Id Reuse Policy? {#workflow-id-reuse-policy}

A Workflow Id Reuse Policy determines whether a Workflow Execution is allowed to spawn with a particular Workflow Id, if that Workflow Id has been used with a previous, and now Closed, Workflow Execution.

It is not possible for a new Workflow Execution to spawn with the same Workflow Id as another Open Workflow Execution, regardless of the Workflow Id Reuse Policy.

See [Workflow Id Conflict Policy](#workflow-id-conflict-policy) for resolving a Workflow Id conflict.

The Workflow Id Reuse Policy can have one of the following values:

- **Allow Duplicate:** The Workflow Execution is allowed to exist regardless of the Closed status of a previous Workflow Execution with the same Workflow Id.
  **This is the default policy, if one is not specified.**
  Use this when it is OK to have a Workflow Execution with the same Workflow Id as a previous, but now Closed, Workflow Execution.
- **Allow Duplicate Failed Only:** The Workflow Execution is allowed to exist only if a previous Workflow Execution with the same Workflow Id does not have a Completed status.
  Use this policy when there is a need to re-execute a Failed, Timed Out, Terminated, or Cancelled Workflow Execution and guarantee that the Completed Workflow Execution will not be re-executed.
- **Reject Duplicate:** The Workflow Execution cannot exist if a previous Workflow Execution has the same Workflow Id, regardless of the Closed status.
  Use this when there can only be one Workflow Execution per Workflow Id within a Namespace for the given retention period.
- **Terminate if Running:** Specifies that if a Workflow Execution with the same Workflow Id is already running, it should be terminated and a new Workflow Execution with the same Workflow Id should be started. This policy allows for only one Workflow Execution with a specific Workflow Id to be running at any given time.

The first three values (Allow Duplicate, Allow Duplicate Failed Only, and Reject Duplicate) of the Workflow Id Reuse Policy apply to Closed Workflow Executions that are retained within the Namespace.
For example, given a default Retention Period, the Temporal Service can only check the Workflow Id of the spawning Workflow Execution based on the Workflow Id Reuse Policy against the Closed Workflow Executions for the last _30 days_.

If you need to start a Workflow for a particular implementation only if it hasn't started yet, ensure that your Retention Period is long enough to check against.
If this becomes unwieldy, consider using [Workflow message passing](/encyclopedia/workflow-message-passing) instead of trying to start Workflows atomically.

The fourth value of the Workflow Id Reuse Policy, Terminate if Running, only applies to a Workflow Execution that is currently open within the Namespace.
For Terminate if Running, the Retention Period is not a consideration for this policy.

If there is an attempt to spawn a Workflow Execution with a Workflow Id Reuse Policy that won't allow it, the Server will prevent the Workflow Execution from spawning.

### What is a Workflow Id Conflict Policy? {#workflow-id-conflict-policy}

A Workflow Id Conflict Policy determines how to resolve a conflict when spawning a new Workflow Execution with a particular Workflow Id used by an existing Open Workflow Execution.
See [Workflow Id Reuse Policy](#workflow-id-reuse-policy) for managing the reuse of a Workflow Id of a Closed Workflow.

By default, this results in a `Workflow execution already started` error.

:::note

The default [StartWorkflowOptions](https://pkg.go.dev/go.temporal.io/sdk/internal#StartWorkflowOptions) behavior in the Go SDK is to not return an error when a new Workflow Execution is attempted with the same Workflow Id as an Open Workflow Execution.
Instead, it returns a WorkflowRun instance representing the current or last run of the Open Workflow Execution.

To return the `Workflow execution already started` error, set `WorkflowExecutionErrorWhenAlreadyStarted` to `true`.

:::

The Workflow Id Conflict Policy can have one of the following values:

- **Fail:** Prevents the Workflow Execution from spawning and returns a `Workflow execution already started` error.
  **This is the default policy, if one isn't specified.**
- **Use Existing:** Prevents the Workflow Execution from spawning and returns a successful response with the Open Workflow Execution's Run Id.
- **Terminate Existing:** Terminates the Open Workflow Execution then spawns the new Workflow Execution with the same Workflow Id.

---

## Temporal Workflow

This guide provides a comprehensive overview of Temporal Workflows and covers the following:

- [Workflow Definition](/workflow-definition)
- [Workflow Execution](/workflow-execution)
- [Schedules](/schedule)
- [Dynamic Handler](/dynamic-handler)
- [Cron Job](/cron-job)

## Intro to Workflows

Conceptually, a workflow defines a sequence of steps. With Temporal, those steps are defined by writing code, known as a
Workflow Definition, and are carried out by running that code, which results in a Workflow Execution.

In day-to-day conversations, the term Workflow might refer to Workflow Type, a Workflow Definition, or a Workflow
Execution.

1. A **Workflow Definition** is the code that defines your Workflow.
2. The **Workflow Type** is the name that maps to a Workflow Definition. It's an identifier that makes it possible to
   distinguish one type of Workflow (such as order processing) from another (such as customer onboarding).
3. A **Workflow Execution** is a running Workflow, which is created by combining a Workflow Definition with a request to
   execute it. You can execute a Workflow Definition any number of times, potentially providing different input each
   time (i.e., a Workflow Definition for order processing might process order #123 in one execution and order #567 in
   another execution). It is the actual instance of the Workflow Definition running in the Temporal Platform.

You'll develop those Workflows by writing code in a general-purpose programming language such as Go, Java, TypeScript,
or Python. The code you write is the same code that will be executed at runtime, so you can use your favorite tools and
libraries to develop Temporal Workflows.

Temporal Workflows are resilient. They can run—and keep running—for years, even if the underlying infrastructure fails.
If the application itself crashes, Temporal will automatically recreate its pre-failure state so it can continue right
where it left off.

Each Workflow Execution progresses through a series of **Commands** and **Events**, which are recorded in an **Event
History**.

Workflows must follow deterministic constraints to ensure consistent replay behavior.

---

## Handling Signals, Queries, & Updates

When Signals, Updates, and Queries arrive at your Workflow, the handlers for these messages will operate on the current state of your Workflow and can use the fields you have set.
In this section, we’ll give you an overview of how messages work with Temporal and cover how to write correct and robust handlers by covering topics like atomicity, guaranteeing completion before the Workflow exits, exceptions, and idempotency.

## Handling Messages {#handling-messages}

### Message handler concurrency {#message-handler-concurrency}

If your Workflow receives messages, you may need to consider how those messages interact with one another or with the main Workflow method.
Behind the scenes, Temporal is running a loop that looks like this:

<CaptionedImage
    src="/img/info/messages-workflow-loop.png"
    title="Diagram that shows the execution ordering of Workflows" />

Every time the Workflow wakes up--generally, it wakes up when it needs to--it will process messages in the order they were received, followed by making progress in the Workflow’s main method.

This execution is on a single thread–while this means you don’t have to worry about parallelism, you do need to worry about concurrency if you have written Signal and Update handlers that can block. These can run interleaved with the main Workflow and with one another, resulting in potential race conditions. These methods should be made reentrant.

#### Initializing the Workflow first {#workflow-initializers}

Initialize your Workflow's state before handling messages.
This prevents your handler from reading uninitialized instance variables.

To see why, refer to the [diagram](#message-handler-concurrency).
It shows that your Workflow processes messages before the first run of your Workflow's main method.

The message handler runs first in several scenarios, such as:

- When using [Signal-with-Start](/sending-messages#signal-with-start).
- When your Worker experiences delays, such as when the Task Queue it polls gets backlogged.
- When messages arrive immediately after a Workflow continues as new but before it resumes.

For all languages except Go and TypeScript, use your constructor to set up state.
Annotate your constructor as a Workflow Initializer and take the same arguments as your Workflow's main method.

Note that you can't make blocking calls from your constructor.
If you need to block, make your Signal or Update handler [wait](#waiting) for an initialization flag.

In Go and TypeScript, register any message handlers only after completing initialization.

### Message handler patterns {#message-handler-patterns}

Here are several common patterns for write operations, Signal and Update handlers. They don't apply to pure read operations, i.e. Queries or [Update Validators](/handling-messages#update-validators):

- Returning immediately from a handler
- Waiting for the Workflow to be ready to process them
- Kicking off activities and other asynchronous tasks
- Injecting work into the main Workflow
- Finishing handlers before the Workflow completes
- Ensuring your messages are processed exactly once

#### Synchronous handlers

Synchronous handlers don’t kick off any long-running operations or otherwise block. They're guaranteed to run atomically.

#### Waiting {#waiting}

A Signal or Update handler can block waiting for the Workflow to reach a certain state using a Wait Condition. See the links below to find out how to use this with your SDK.

#### Running asynchronous tasks

Sometimes, you need your message handler to wait for long-running operations such as executing an Activity. When this happens, the handler will yield control back to [the loop](#message-handler-concurrency). This means that your handlers can have race conditions if you’re not careful.
You can guard your handlers with concurrency primitives like mutexes or semaphores, but you should use versions of these primitives provided for Workflows in most languages. See the links below for examples of how to use them in your SDK.

#### Inject work into the main Workflow {#injecting-work-into-main-workflow}

Sometimes you want to process work provided by messages in the main Workflow. Perhaps you’d like to accumulate several messages before acting on any of them. For example, message handlers might put work into a queue, which can then be picked up and processed in an event loop that you yourself write.
This option is considered advanced but offers powerful flexibility. And if you serialize the handling of your messages inside your main Workflow, you can avoid using concurrency primitives like mutexes and semaphores. See the links above for how to do this in your SDK.

#### Finishing handlers before the Workflow completes {#finishing-message-handlers}

You should generally finish running all handlers before the Workflow run completes or continues as new. For some Workflows, this means you should explicitly check to make sure that all the handlers have completed before finishing. You can await a condition called All Handlers Finished at the end of your Workflow.

If you don’t need to ensure that your handlers complete, you may specify your handler’s Handler Unfinished Policy as Abandon to turn off the warnings. However, note that clients waiting for Updates will get Not Found errors if they're waiting for Updates that never complete before the Workflow run completes.

See the links below for how to ensure handlers are finished in your SDK.

#### Ensuring your messages are processed exactly once {#exactly-once-message-processing}

Many developers want their message handlers to run exactly once--to be idempotent--in cases where the same Signal or Update is delivered twice or sent by two different call sites. Temporal deduplicates messages for you on the server, but there is one important case when you need to think about this yourself when authoring a Workflow, and one when sending Signals and Updates.

When your workflow Continues-As-New, you should handle deduplication yourself in your message handler. This is because Temporal's built-in deduplication doesn't work across [Continue-As-New](/workflow-execution/continue-as-new) boundaries, meaning you would risk processing messages twice for such Workflows if you don't check for duplicate messages yourself.

To deduplicate in your message handler, you can use an idempotency key.

Clients can provide an idempotency key. This can be important because Temporal's SDKs provide a randomized key by default, which means Temporal only deduplicates retries from the same call. For Updates, if you craft an Update ID, Temporal will deduplicate any calls that use that key. This is useful when you have two different callsites that may send the same Update, or when your client itself may get retried. For Signals, you can provide a key as part of your Signal arguments.

Inside your message handler, you can check your idempotency key--the Update ID or the one you provided to the Signal--to check whether the Workflow has already handled the update.

See the links below for examples of solving this in your SDK.

#### Authoring message handler patterns

See examples of the above patterns.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/dotnet/message-passing" text="Author message handler patterns in .NET" archetype="feature-guide" />
    <RelatedReadItem path="/develop/go/message-passing#message-handler-patterns" text="Author message handler patterns in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing" text="Author message handler patterns in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing" text="Author message handler patterns in PHP" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#message-handler-patterns" text="Author message handler patterns in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#message-handler-patterns" text="Author message handler patterns in TypeScript" archetype="feature-guide" />
</RelatedReadContainer>

### Update Validators {#update-validators}

When you define an Update handler, you may optionally define an Update Validator: a read operation that's responsible for accepting or rejecting the Update. You can use Validators to verify arguments or make sure the Workflow is ready to accept your Updates.

- If it accepts, the Update will become part of your Workflow’s history and the client will be notified that the operation has been Accepted. The Update handler will then run until it returns a value.
- If it rejects, the client will be informed that it was Rejected, and the Workflow will have no indication that it was ever requested, similar to a Query handler.

:::note

Like Queries, Validators are not allowed to block.

:::

Once the Update handler is finished and has returned a value, the operation is considered Completed.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#updates" text="Validate updates in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#updates" text="Validate updates in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#updates" text="Validate updates in .NET" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#updates" text="Validate updates in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#updates" text="Validate updates in TypeScript" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#handle-updates" text="Validate updates in PHP" archetype="feature-guide" />
</RelatedReadContainer>

### Exceptions in message handlers {#exceptions}

When throwing an exception in a message handler, you should decide whether to make it an [Application Failure](/references/failures#application-failure). The implications are different between Signals and Updates.

:::caution
The following content applies in every SDK except the Go SDK. See below.
:::

#### Exceptions in Signals

In Signal handlers, throw [Application Failures](/references/failures#application-failure) only for unrecoverable errors, because the entire Workflow will fail.
Similarly, allowing a failing Activity or Child Workflow to exhaust its retries, so that it throws an [Activity Failure](https://docs.temporal.io/references/failures#activity-failure) or [Child Workflow Failure](https://docs.temporal.io/references/failures#child-workflow-failure) will cause the entire Workflow to fail.
Note that for Activities, this will only happen if you change the default Activity [Retry Policy](https://docs.temporal.io/encyclopedia/retry-policies), since by default they retry forever.
If you throw any other exception, by default, it will cause a [Workflow Task Failure](/references/failures#workflow-task-failures). This means the Workflow will get stuck and will retry the handler periodically until the exception is fixed, for example by a code change.

#### Exceptions in Updates

Doing any of the following will fail the Update and cause the client to receive the error:

- Reject the Update by throwing any exception from your [Validator](https://docs.temporal.io/handling-messages#update-validators).
- Allow a failing Activity or Child Workflow to exhaust its retries, so that it throws an [Activity Failure](https://docs.temporal.io/references/failures#activity-failure) or [Child Workflow Failure](https://docs.temporal.io/references/failures#child-workflow-failure). Note that for Activities, this will only happen if you change the default Activity [Retry Policy](https://docs.temporal.io/encyclopedia/retry-policies), since by default they retry forever.
- Throw an [Application Failure](/references/failures#application-failure) from your Update handler.

Unlike with Signals, the Workflow will keep going in these cases.

If you throw any other exception, by default, it will cause a [Workflow Task Failure](/references/failures#workflow-task-failures). This means the Workflow will get stuck and will retry the handler periodically until the exception is fixed, for example by a code change or infrastructure coming back online. Note that this will cause a delay for clients waiting for an Update result.

#### Errors and panics in message handlers in the Go SDK

In Go, returning an error behaves like an [Application Failure](/references/failures#application-failure) in the other SDKs. Panics behave like non-Application Failure exceptions in other languages, in that they cause a [Workflow Task Failure](/references/failures#workflow-task-failures).

### Writing Signal Handlers {#writing-signal-handlers}

Use these links to see a simple Signal handler.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#signals" text="Handle Signals in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#signals" text="Handle Signals in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#signals" text="Handle Signals in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#signals" text="Handle Signals in TypeScript" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#signals" text="Handle Signals in .NET" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#handle-signal" text="Handle Signals in PHP" archetype="feature-guide" />
</RelatedReadContainer>

### Writing Update Handlers {#writing-update-handlers}

Use these links to see a simple update handler.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#updates" text="Handle Updates in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#updates" text="Handle Updates in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#updates" text="Handle Updates in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#updates" text="Handle Updates in TypeScript" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#updates" text="Handle Updates in .NET" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#handle-updates" text="Handle Updates in PHP" archetype="feature-guide" />
</RelatedReadContainer>

### Writing Query Handlers {#writing-query-handlers}

Author queries using these per-language guides.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#queries" text="Handle Queries in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#queries" text="Handle Queries in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#queries" text="Handle Queries in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#queries" text="Handle Queries in TypeScript" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#queries" text="Handle Queries in .NET" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#handle-query" text="Handle Queries in PHP" archetype="feature-guide" />
</RelatedReadContainer>

---

## Sending Signals, Queries, & Updates

This section will help you write clients that send messages to Workflows which includes:

- [Sending Signals](#sending-signals)
- [Sending Updates](#sending-updates)
- [Sending Queries](#sending-queries)

### Sending Signals {#sending-signals}

You can send Signals from any Temporal Client, the Temporal CLI, or you can Signal one Workflow to another.

You can also Signal-With-Start to lazily initialize a Workflow while sending a Signal.

#### Send a Signal from a Temporal Client or the CLI

<RelatedReadContainer>
    <RelatedReadItem path="/cli/workflow#signal" text="Send a Signal using the Temporal CLI" archetype="feature-guide" />
    <RelatedReadItem path="/develop/go/message-passing#send-signal-from-client" text="Send Signals with the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#send-signal-from-client" text="Send Signals with the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#send-signal-from-client" text="Send Signals with the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#send-signal-from-client" text="Send Signals with the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#send-signal-from-client" text="Send Signals with the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#send-signal-from-client" text="Send Signals with the .NET SDK" archetype="feature-guide" />
</RelatedReadContainer>

#### Send a Signal from one Workflow to another

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#send-signal-from-workflow" text="Send Signals from Workflows with the .NET SDK" archetype="feature-guide" />
</RelatedReadContainer>

#### Signal-With-Start {#signal-with-start}

Signal-With-Start is a great tool for lazily initializing Workflows. When you send this operation, if there is a running Workflow Execution with the given Workflow Id, it will be Signaled. Otherwise, a new Workflow Execution starts and is immediately sent the Signal.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#signal-with-start" text="Signal-With-Start using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#signal-with-start" text="Signal-With-Start using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#signal-with-start" text="Signal-With-Start using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#signal-with-start" text="Signal-With-Start using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#signal-with-start" text="Signal-With-Start using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#signal-with-start" text="Signal-With-Start using the .NET SDK" archetype="feature-guide" />
</RelatedReadContainer>

### Sending Updates {#sending-updates}

:::note

To use the Workflow Update feature in versions prior to v1.25.0, it must be manually enabled.

Set the [frontend.enableUpdateWorkflowExecution](https://github.com/temporalio/temporal/blob/main/common/dynamicconfig/constants.go) and [frontend.enableUpdateWorkflowExecutionAsyncAccepted](https://github.com/temporalio/temporal/blob/main/common/dynamicconfig/constants.go) dynamic config values to `true`.

For example, with the Temporal CLI, run these commands:

```command
temporal server start-dev --dynamic-config-value frontend.enableUpdateWorkflowExecution=true
temporal server start-dev --dynamic-config-value frontend.enableUpdateWorkflowExecutionAsyncAccepted=true
```

:::

Updates can be sent from a Temporal Client or the Temporal CLI to a Workflow Execution. This call is synchronous and will call into the corresponding Update handler. If you’d rather make an asynchronous request, you should use Signals.

In most languages (except Go), you may call `executeUpdate` to complete an Update and get its result.

Alternatively, to start an Update, you may call `startUpdate` and pass in the Workflow Update Stage as an argument. You have two choices on what to await:

- Accepted - wait until the Worker is contacted, which ensures that the Update is persisted. See [Update Validators](/handling-messages#update-validators) for more information.
- Completed - wait until the handler finishes and returns a result. (This is equivalent to `executeUpdate`.)

The start call will give you a handle you can use to track the Update, determine whether it was Accepted, and ultimately get its result or an error.

If you want to send an Update to another Workflow such as a Child Workflow from within a Workflow, you should do so within an Activity and use the Temporal Client as normal.

There are limits on the total number of Updates that may occur during a Workflow Execution run, and also on the number of concurrent in-progress Updates that a Workflow Execution may have.
Use [Update Validators](/handling-messages#update-validators) and [Update IDs](/handling-messages#exactly-once-message-processing) to stay within the system limits in both [Cloud](/cloud/limits#per-workflow-execution-update-limits) and [Self-Hosted](/self-hosted-guide/defaults).

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#send-update-from-client" text="Send Updates in Go" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#send-update-from-client" text="Send Updates in Java" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#send-update-from-client" text="Send Updates in PHP" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#send-update-from-client" text="Send Updates in Python" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#send-update-from-client" text="Send Updates in TypeScript" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#send-update-from-client" text="Send Updates in .NET" archetype="feature-guide" />
</RelatedReadContainer>

#### Update-With-Start {#update-with-start}

:::tip

For open source server users, Temporal Server version [Temporal Server version 1.28](https://github.com/temporalio/temporal/releases/tag/v1.28.0) is recommended.

:::

Update-with-Start sends an Update request, starting a Workflow if necessary.
A [`WorkflowIDConflictPolicy`](https://docs.temporal.io/workflow-execution/workflowid-runid#workflow-id-conflict-policy) must be specified.
Workflow ID and Update ID can be used as idempotency keys as follows:

- If the Workflow exists and you provided an Update ID, and the Update exists in the latest Workflow Run, then Update-With-Start attaches to the existing Update (regardless of `WorkflowIDConflictPolicy`)
  - If the Workflow is closed, it attaches only if the Update has completed.
- Otherwise it uses [`WorkflowIDConflictPolicy`](https://docs.temporal.io/workflow-execution/workflowid-runid#workflow-id-conflict-policy) and [`WorkflowIDReusePolicy`](https://docs.temporal.io/workflow-execution/workflowid-runid#workflow-id-reuse-policy) as usual to determine whether to start a Workflow, and then starts a new Update immediately.

Update-With-Start is great for latency-sensitive use cases:

- **Lazy Initialization** -
  Instead of making separate Start Workflow and Update Workflow calls, Update-With-Start allows you to send them together in a single roundtrip.
  For example, a shopping cart can be modeled using Update-With-Start.
  Updates let you add and remove items from the cart.
  Update-With-Start lets the customer start shopping, whether the cart already exists or they've just started shopping.
  It ensures the cart, modeled by a Workflow Execution, exists before applying any Update that changes the state of items within the cart.
  Set your `WorkflowIDConflictPolicy` to `USE_EXISTING` for this pattern.
- **Early Return** -
  Using Update-With-Start you can begin a new Workflow Execution and synchronously receive a response, while the Workflow Execution continues to run to completion.
  For example, you might model a payment process using Update-With-Start.
  This allows you to send the payment validation results back to the client synchronously, while the transaction Workflow continues in the background.
  Set your `WorkflowIDConflictPolicy` to `FAIL` and use a unique Update ID for this pattern if you want to assert it does not reuse an existing Workflow.

:::caution

Unlike Signal-with-Start - Update-With-Start is _not_ atomic.
If the Update can't be delivered, for example, because there's no running Worker available, a new Workflow Execution will still start.
The SDKs will retry the Update-With-Start request, but there is no guarantee that the Update will succeed.

:::

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/message-passing#update-with-start" text="Update-With-Start with the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#update-with-start" text="Update-With-Start with the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#update-with-start" text="Update-With-Start with the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#update-with-start" text="Update-With-Start with the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#update-with-start" text="Update-With-Start with the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#update-with-start" text="Update-With-Start with the .NET SDK" archetype="feature-guide" />
</RelatedReadContainer>

### Sending Queries {#sending-queries}

Queries can be sent from a Temporal Client or the Temporal CLI to a Workflow Execution--even if this Workflow has Completed. This call is synchronous and will call into the corresponding Query handler.
You can also send a built-in "Stack Trace Query" for debugging.

<RelatedReadContainer>
    <RelatedReadItem path="/cli/workflow#query" text="Send a Query using the Temporal CLI" archetype="feature-guide" />
    <RelatedReadItem path="/develop/go/message-passing#send-query" text="Send a Query with the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/message-passing#send-query" text="Send a Query with the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/message-passing#send-query" text="Send a Query with the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/message-passing#send-query" text="Send a Query with the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/message-passing#send-query" text="Send a Query with the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/message-passing#send-query" text="Send a Query with the .NET SDK" archetype="feature-guide" />
</RelatedReadContainer>

#### Stack Trace Query {#stack-trace-query}

In many SDKs, the Temporal Client exposes a predefined `__stack_trace` Query that returns the call stack of all the threads owned by that Workflow Execution.
This is a great way to troubleshoot a Workflow Execution in production.
For example, if a Workflow Execution has been stuck at a state for longer than an expected period of time, you can send a `__stack_trace` Query to return the current call stack.
The `__stack_trace` Query name does not require special handling in your Workflow code.

:::note

Stack Trace Queries are available only for running Workflow Executions.

:::

---

## Temporal Workflow message passing - Signals, Queries, & Updates

Workflows can be thought of as stateful web services that can receive messages. The Workflow can have powerful message
handlers akin to endpoints that react to the incoming messages in combination with the current state of the Workflow.
Temporal supports three types of messages: Signals, Queries, and Updates:

- Queries are read requests. They can read the current state of the Workflow but cannot block in doing so.
- Signals are asynchronous write requests. They cause changes in the running Workflow, but you cannot await any response
  or error.
- Updates are synchronous, tracked write requests. The sender of the Update can wait for a response on completion or an
  error on failure.

## How to choose between Signals, Updates, and Queries as a Workflow author? {#choosing-messages}

This section will help you write Workflows that receive messages.

### For write requests

Unlike Signals, Updates must be synchronous and must wait for the Worker running the Workflow to acknowledge the
request.

The following table compares when to use **Signals** versus **Updates**.

| **Requirement type**           | **Use Signals when...**                                                                     | **Use Updates when...**                                                                                                                                                                    |
| ------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Asynchronous communication** | Clients want to quickly move on after sending an asynchronous message.                      | Clients want to track the completion of the message.                                                                                                                                       |
| **Result handling**            | Clients are okay with “fire and forget” — no result or exception needed.                    | Clients need a result or exception without performing a query.                                                                                                                             |
| **Worker availability**        | Clients don't depend on the Worker being available.                                         | You want to validate the Update before accepting it into the Workflow and its history.                                                                                                     |
| **Concurrency and throughput** | You don’t want to limit the number of messages processed concurrently by a single Workflow. | You don’t need more concurrent Updates per Workflow than the allowed limits for [Cloud](/cloud/limits#per-workflow-execution-update-limits) or [Self-Hosted](/self-hosted-guide/defaults). |
| **Latency sensitivity**        | Since clients don’t expect a result, latency is often not relevant when using Signals.      | Clients want a low-latency end-to-end operation and are willing to wait for completion or validation.                                                                                      |

### For read requests

You normally want to do a Query, because:

- Queries are efficient–they never add entries to the [Workflow Event History](/workflow-execution/event#event-history),
  whereas an Update would (if accepted).
- Queries can operate on completed Workflows.

However, because Queries cannot block, sometimes Updates are best. When your goal is to do a read once the Workflow
achieves a certain desired state, you have two options:

- You could poll periodically with Queries until the Workflow is ready.
- You could write your read operation as an Update, which will give you better efficiency and latency, though it will
  write an entry to the [Workflow Event History](/workflow-execution/event#event-history).

### For read/write requests

Use an Update for synchronous read/write requests. If your request must be asynchronous, consider sending a Signal
followed by polling with a Query.

---

## Cloud automation - Temporal feature

Temporal Cloud Automation changes the way how you manage and scale your cloud infrastructure.
Its features enable you to automate critical tasks like user and namespace management, mTLS certificate rotation, and access control, ensuring security and operational efficiency.
Cloud Automation offers secure authentication across all interfaces, reducing errors and enhancing security.

**Key Features:**

- [Secure API Keys](https://docs.temporal.io/cloud/api-keys): Manage resources securely with Temporal Cloud API Keys.
- [Temporal Cloud CLI (tcld)](https://docs.temporal.io/cloud/tcld): Automate operations directly from the command line.
- [Terraform Provider for Cloud](https://docs.temporal.io/cloud/terraform-provider#prerequisites): Scale effortlessly with infrastructure-as-code.

<RelatedReadContainer>
  <RelatedReadItem path="https://docs.temporal.io/cloud/api-keys" text="API Keys documentation" archetype="cloud-guide" />
  <RelatedReadItem path="https://docs.temporal.io/ops?_gl=1*1yf937l*_gcl_au*MTg1MTAxMTEwNC4xNzEzOTcxMjYw*_ga*MTgwODU1MzQyNi4xNzA3NzA4ODIz*_ga_R90Q9SJD3D*MTcyMTI0MTAyNy41MjIuMS4xNzIxMjQ5NTYxLjAuMC4w" text="Cloud Ops API documentation" archetype="cloud-guide" />
  <RelatedReadItem path="/cloud/tcld" text="Temporal Cloud CLI" archetype="cloud-guide" />
  <RelatedReadItem path="/cloud/terraform-provider" text="Terraform Provider for Cloud" archetype="cloud-guide" />
</RelatedReadContainer>

From centralizing cloud operations and automating certificate rotation to streamlining user management and onboarding new teams, Temporal's Cloud Automation features covers a wide range of use cases that enhance efficiency and security across your organization.

---

## Temporal's production deployment features

Transform your Temporal applications into production-ready systems by deploying your application code, Workflows, Activities, and Workers for operational use.
When your application is ready to start serving production traffic, we offer two Temporal Service options:

- **[Choose Temporal Cloud for your Temporal Service](/cloud)**
  Let us handle the Temporal Service operations so you can focus on your applications.
- **[Self-host a Temporal Service](/self-hosted-guide)**
  Deploy your own production level Temporal Service to orchestrate your durable applications.

| Feature                            | Temporal Cloud                                                            | Self-hosted                                      |
| ---------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------ |
| **Multi-tenant**                   | ✅ Up to 100 Namespaces                                                   | ✅ Unlimited Namespaces                          |
| **High availability and failover** | ✅ [Namespaces with High Availability features](/cloud/high-availability) | ✅ Global Namespaces & Multi-Cluster Replication |
| **Application state persistence**  | ✅ 30-90 day Retention                                                    | ✅ Unlimited                                     |
| **Long term state retention**      | ✅ Workflow History Export                                                | ✅ Archival                                      |
| **Community support**              | ✅ Slack, Forum                                                           | ✅ Slack, Forum                                  |
| **Paid support**                   | ✅ Prioritized responses                                                  | ✖️                                                |

---

## Core application - Temporal feature

**Workflows**, **Activities**, and **Workers** form the core parts of a Temporal Application.

**Workflows**: A Workflow defines the overall flow of the application.
You write it in your programming language of choice using the Temporal SDK.
Conceptually, a Workflow specifies a sequence of steps and orchestrates the execution of Activities.

**Activities**: An Activity is a method or function that encapsulates business logic prone to failure (e.g., calling a service that may go down).
The system can automatically retry these Activities upon some failures.
Activities perform a single, well-defined action, such as calling another service, transcoding a media file, or sending an email message.

**Workers**: A Worker executes your Workflow and Activity code.

**Follow one of our tutorials to [Get started](https://learn.temporal.io/getting_started/) learning how to develop Workflows and Activities and run them in Worker Processes.**

Or jump straight to a Temporal SDK feature guide:

<RelatedReadContainer>
  <RelatedReadItem path="/develop/go/core-application" text="Go SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/java/core-application" text="Java SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/php/core-application" text="PHP SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/python/core-application" text="Python SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/typescript/core-application#connect-to-a-dev-cluster" text="TypeScript SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/dotnet/core-application" text=".NET SDK Core application feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/ruby/core-application" text="Ruby SDK Core application feature guide" archetype="feature-guide" />
</RelatedReadContainer>

For a deep dive into Temporal Workflows, Activities, and Workers, visit the following Temporal Encyclopedia pages or enroll in one of [our courses](https://learn.temporal.io/courses/).

- [Temporal Workflows](/workflows)
- [Temporal Activities](/activities)
- [Temporal Workers](/workers)

---

## Data encryption - Temporal feature

Data Converters in Temporal are SDK components that handle the serialization and encoding of data transmitted and received by a Temporal Client.
Workflow input and output need to be serialized and deserialized so they can be sent as JSON to the Temporal Service.

Temporal provides its own default Data Converter logic, which is not apparent to a user if payloads contain plain text or JSON data.
For enhanced security, you can implement your own encryption standards using a Codec Server.
Temporal's data encryption capabilities ensures the security and confidentiality of your Workflows and provides protection without compromising performance.

Jump straight to a Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/converters-and-encryption" text="Data Encryption using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/converters-and-encryption" text="Data Encryption using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/converters-and-encryption" text="Data Encryption using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/converters-and-encryption" text="Data Encryption using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/converters-and-encryption" text="Data Encryption using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/converters-and-encryption" text="Data Encryption using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

---

## Debugging - Temporal feature

Temporal offers powerful and efficient debugging capabilities for both development and production. These capabilities help developers inspect and troubleshoot Workflows and Activities with precision, ensuring that Workflows perform as expected.

By leveraging detailed event histories and intuitive tooling, you can trace the execution path of Workflows, identify issues, and understand the state of your application at any given point in time.

Jump straight to a Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/debugging" text="Debugging using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/debugging" text="Debugging using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/debugging" text="Debugging using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/debugging" text="Debugging using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/debugging" text="Debugging using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/debugging" text="Debugging using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/debugging" text="Debugging using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

---

## Failure detection - Temporal feature

In Temporal, timeouts detect application failures.
The system can then automatically mitigate these failures through retries.
Both major application function primitives, **Workflows** and **Activities**, have dedicated **timeout configurations** and can be configured with a **Retry Policy**.

**Follow one of our tutorials to [Get started](https://learn.temporal.io/getting_started/) exploring timeouts and Retry Policies.**

Or jump straight to a Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/failure-detection#workflow-timeouts" text="Set Workflow timeouts and Retry Policies using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

<RelatedReadContainer>
  <RelatedReadItem path="/develop/go/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the Go SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/java/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the Java SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/php/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the PHP SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/python/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the Python SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/typescript/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the TypeScript SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/dotnet/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the .NET SDK" archetype="feature-guide" />
  <RelatedReadItem path="/develop/ruby/failure-detection#activity-timeouts" text="Set Activity timeouts and Retry Policies using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

For a deep dive into timeouts and Retry Policies visit the following Temporal Encyclopedia pages or enroll in one of [our courses](https://learn.temporal.io/courses/).

<RelatedReadContainer>
    <RelatedReadItem path="/encyclopedia/detecting-workflow-failures" text="Detecting Workflow failures" archetype="encyclopedia" />
    <RelatedReadItem path="/encyclopedia/detecting-activity-failures" text="Detecting Activity failures" archetype="encyclopedia" />
    <RelatedReadItem path="/encyclopedia/retry-policies" text="Retry Policies" archetype="encyclopedia" />
</RelatedReadContainer>

---

## Temporal development and production features

Through a Temporal SDK, Temporal provides a wide range of features that enable developers to build applications that serve a wide range of use cases.

- **[Core application primitives](/evaluate/development-production-features/core-application)**: Develop and run your application with Workflows, Activities, and Workers.
- **[Testing suite](/evaluate/development-production-features/testing-suite)**: Each Temporal SDK comes with a testing suite that enables developers to test their applications as they would any other.
- **[Scheduled Workflows](/evaluate/development-production-features/schedules)**: Start a business process at a specific time or on a given time interval.
- **[Interrupt a Workflow](/evaluate/development-production-features/interrupt-workflow)**: Cancel or terminate a business process (Workflow) that is already in progress and compensate for any steps already taken.
- **Runtime safeguards**: Prevent avoidable errors and issues from executing during runtime.
- **[Failure detection and mitigation](/evaluate/development-production-features/failure-detection)**: Detect failures with timeouts and configure automatic retries to mitigate them.
- **[Temporal Nexus](/evaluate/nexus)**: Connect Temporal Applications across (and within) isolated Namespaces for improved modularity, security, debugging, and fault isolation. Nexus supports cross-team, cross-domain, and multi-region use cases.
- **[Workflow message passing](/evaluate/development-production-features/workflow-message-passing)**: Build responsive applications that react to events at runtime and enable data retrieval from ongoing Workflows.
- **Versioning**: Support multiple versions of your business logic for long-running business processes.
- **[Observability](/evaluate/development-production-features/observability)**: List business process, view their state, and set up dashboards with metrics.
- **[Debugging](/evaluate/development-production-features/debugging)**: Surface errors and step through code to find issues.
- **[Data encryption](/evaluate/development-production-features/data-encryption)**: Transform data and protect the privacy of the users of your application.
- **[Throughput composability](/evaluate/development-production-features/throughput-composability)**: Breakup business processes by data streams, team ownership, or other organization factors.
- **[Cloud Automation](/evaluate/development-production-features/cloud-automation)**: Simplify cloud management and boost security with Temporal's Cloud Automation.
- **[Low Latency](/evaluate/development-production-features/low-latency)**: Making your applications faster, more performant, and more efficient.
- **[Multi-tenancy](/evaluate/development-production-features/multi-tenancy)**: Enhances efficiency and cost-effectiveness.

For detailed information on Temporal feature release stages and criteria, see this [Product Release Stages Guide](/evaluate/development-production-features/release-stages).

---

## Interrupt a Workflow - Cancellation and Termination

Discover how Temporal enables you to gracefully handle Workflow interruptions through cancellations and terminations.
Understand how to stop a Workflow cleanly with cancellation, allowing for proper cleanup and state management.

For situations where a Workflow is stuck, termination provides an immediate solution, ensuring your applications remain
robust and responsive.

<RelatedReadContainer>
  <RelatedReadItem
    path="/develop/go/cancellation"
    text="Handling Cancellation and Termination using the Go SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/java/cancellation"
    text="Handling Cancellation and Termination using the Java SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/php/cancellation"
    text="Handling Cancellation and Termination using the PHP SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/python/cancellation"
    text="Handling Cancellation and Termination using the Python SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/typescript/cancellation"
    text="Handling Cancellation and Termination using the TypeScript SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/dotnet/cancellation"
    text="Handling Cancellation and Termination using the .NET SDK"
    archetype="feature-guide"
  />
  <RelatedReadItem
    path="/develop/ruby/interrupt-workflow"
    text="Handling Cancellation and Termination using the Ruby SDK"
    archetype="feature-guide"
  />
</RelatedReadContainer>

---

## Low latency - Temporal feature

Temporal Cloud provides features that significantly reduce latency compared to self-hosted instances, making your applications faster, more performant, and more efficient.
In the world of modern applications, low latency is crucial for ensuring minimal delay in Workflow Executions.
This low-latency architecture ensures rapid Workflow Execution and responsiveness, critical for time-sensitive applications and high-performance systems.

Temporal Cloud's custom persistence layer incorporates three key components that contribute to low latency:

- **Better Sharding:** Distributes load across multiple databases, preventing bottlenecks.
  Enables independent resizing, improving scalability and handling high-traffic events without delay.
- **Write-Ahead Log (WAL):** Aggregates updates before writing to the database, reducing write latency.
  Stores writes in an append-only format, reducing latency and database size by batching updates before writing to the database.
- **Tiered Storage of Workflow Event History:** Offloads completed Workflow Event Histories, improving database efficiency.

Temporal Cloud provides lower latency, making it suitable for latency-sensitive, large-scale, or business-critical applications.

<RelatedReadContainer>
  <RelatedReadItem path="https://temporal.io/blog/exploring-temporal-cloud-automation-features" text="Exploring Temporal Cloud Automation Features" archetype="blog-post" />
  <RelatedReadItem path="https://temporal.io/blog/high-availability-and-disaster-recovery-with-temporal-cloud" text="High Availability and Disaster Recovery with Temporal Cloud" archetype="blog-post" />
  <RelatedReadItem path="https://temporal.io/blog/higher-throughput-and-lower-latency-temporal-clouds-custom-persistence-layer" text="Higher throughput and lower latency: Temporal Cloud’s custom persistence layer" archetype="blog-post" />
  <RelatedReadItem path="https://temporal.io/blog/how-to-migrate-your-self-hosted-service-to-temporal-cloud" text="How to Migrate Your Self-Hosted Service to Temporal Cloud" archetype="blog-post" />
  <RelatedReadItem path="https://temporal.io/blog/scaling-temporal-the-basics" text="Scaling your self-hosted instance" archetype="blog-post" />
  <RelatedReadItem path="https://temporal.io/blog/benchmarking-latency-temporal-cloud-vs-self-hosted-temporal" text="Benchmarking Latency: Temporal Cloud vs. Self-Hosted Temporal" archetype="blog-post" />
  <RelatedReadItem path="https://docs.temporal.io/cloud/service-availability#latency" text="Temporal Cloud’s Latency SLO" archetype="cloud-guide" />
  <RelatedReadItem path="https://www.youtube.com/watch?v=SQv9ot-jB6o&list=PLl9kRkvFJrlREHL7fiEKBWTp5QuFeYS2r&index=5" text="Replay Conference Talk: Custom Persistence Layer" archetype="replay-talk" />
</RelatedReadContainer>

---

## Multi-tenancy - Temporal feature

Multi-tenancy in Temporal operates at two levels:

## Namespace isolation

[Namespaces](/namespaces) are Temporal's unit of isolation, providing logical separation for multi-tenant deployments in both open source Temporal and Temporal Cloud.

### Open source Temporal

Namespaces in self-hosted Temporal provide:

- **Workflow ID uniqueness**: Temporal guarantees unique Workflow IDs within a Namespace. Different Namespaces can have Workflows with the same ID without conflict.
- **Resource isolation**: Traffic from one Namespace does not impact other Namespaces on the same Temporal Service.
- **Configuration boundaries**: Settings like [Retention Period](/temporal-service/temporal-server#retention-period) and [Archival](/temporal-service/archival) destination are configured per Namespace.
- **Access control**: Use a custom [Authorizer](/self-hosted-guide/security#authorization) on your Frontend Service to restrict who can access each Namespace.
- **Inter-namespace communication**: Use [Nexus](/evaluate/nexus) for controlled communication between Namespaces.

### Temporal Cloud

Temporal Cloud builds on these capabilities with additional isolation guarantees:

- **Independent authentication** via [API keys](/cloud/api-keys) or [mTLS certificates](/cloud/certificates)
- **Built-in [role-based access controls](/cloud/users#namespace-level-permissions)** without custom Authorizer configuration
- **Separate [rate limits](/cloud/limits#namespace-level)** to prevent noisy neighbor problems
- **[High availability replication](/cloud/high-availability)** across regions

<RelatedReadContainer>
  <RelatedReadItem path="/cloud/security#namespace-isolation" text="Namespace Isolation Details" archetype="cloud-guide" />
  <RelatedReadItem path="/cloud/pricing" text="Temporal Cloud Pricing" archetype="cloud-guide" />
</RelatedReadContainer>

## Application multi-tenancy

Many organizations use Temporal to power their own multi-tenant SaaS applications, isolating their customers' workloads using Task Queues, Search Attributes, and Worker design patterns.

See the [multi-tenant application patterns guide](/production-deployment/multi-tenant-patterns) for detailed recommendations on architecting multi-tenant applications with Temporal.

---

## Observability - Temporal feature

Temporal's observability feature helps you track the state of your Workflows in real-time, providing tools for detailed metrics, tracing, comprehensive logging, and visibility into your application state.

Monitor performance, trace Activity and Workflow Executions, debug, and filter Workflow Executions to gain deeper insights into your Workflows.

**Key Components of Temporal's Observability and Visibility**

- **Metrics**: Detailed performance metrics to track the health and efficiency of your Temporal Service and Workflows.
- **Tracing**: End-to-end tracing of Workflow and Activity Executions to understand the flow and timing of operations.
- **Logging**: Comprehensive logging capabilities for debugging and auditing purposes.
- **Search Attributes**: Custom attributes that can be used to enhance searchability and provide additional context to Workflow Executions.
- **Web UI**: A user-friendly interface for visualizing and interacting with your Workflows and Temporal Service state.

**Benefits of Temporal's Observability and Visibility Features**

- **Real-time Monitoring**: Track the state and progress of your Workflows as they execute.
- **Performance Optimization**: Identify bottlenecks and optimize your Workflow and Activity implementations.
- **Effective Debugging**: Quickly locate and diagnose issues in your Temporal applications.
- **Compliance and Auditing**: Maintain detailed records of all Workflow executions for compliance and auditing purposes.
- **Operational Insights**: Gain a deep understanding of your application's behavior and usage patterns.
- **Scalability Management**: Monitor and manage the scalability of your Temporal Service effectively.

Jump straight into the Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/observability" text="Observability using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/observability" text="Observability using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/observability" text="Observability using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/observability" text="Observability using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/observability" text="Observability using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/observability" text="Observability using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/observability" text="Observability using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

---

## Temporal product release stages guide

:::tip CHANGELOG
To stay up-to-date with the latest feature changes, visit the [changelog](https://temporal.io/change-log).
:::

This Product Release Stages Guide provides an understanding of how Temporal features are released. It describes and lists the criteria for each release stage, so that you can make informed decisions about the adoption of each new feature.

Product Release Guide Expectations:

|                                 | Pre-release                                                        | Public Preview                                                                              | General Availability                             |
| ------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| **Features access**             | Self-hosted Temporal users: Everyone; Temporal Cloud: Invite only. | Everyone. Temporal Cloud may limit the number of users being onboarded to ensure stability. | Everyone.                                        |
| **Feature completeness**        | Limited functionality.                                             | Core functionality is complete.                                                             | Mature and feature complete.                     |
| **API stability**               | Experimental; API is subject to change.                            | API breaking changes are kept to a minimum.                                                 | API is stable.                                   |
| **Feature region Availability** | Limited regions.                                                   | Most regions.                                                                               | All [regions](/cloud/regions).                   |
| **Feature support**             | Community and engineering team.                                    | [Formal support](/cloud/support#support-ticket).                                            | [Formal support](/cloud/support#support-ticket). |
| **Feature recommended usage**   | Experimental.                                                      | Production use cases.                                                                       | Production usage.                                |
| **Feature Cloud pricing**       | No additional cost.                                                | Pricing changes are kept to a minimum.                                                      | Pricing is stable.                               |
| **Feature Interoperability**    | Limited.                                                           | Features are compatible with each other, unless otherwise stated.                           | Features are compatible with each other.         |

## Pre-release {#pre-release}

**Access:** Most Pre-release features are released in the open source Temporal software and are publicly available.
However, some features which are explicit to hosting Temporal Services, such as [API Keys](/cloud/api-keys), may be specific to Temporal Cloud.

In Temporal Cloud, Pre-release features are invite-only: Temporal will work directly with a group of existing Temporal Cloud customers to be part of testing of each Pre-release feature.
These customers are invited to provide feedback to the Temporal team.

**Classification:** New features in Pre-release may not be fully mature and may have bugs.
Users acknowledge and agree that Pre-release features are provided on an “as-is” basis, and that they are provided without any indemnification, support, warranties, or representation of any kind.

**Feedback:** Feedback is highly encouraged and important for guiding Temporal feature development.
We encourage you to share your experience so that you can influence the future direction of Temporal.

**Availability:** Temporal may modify features before they become Generally Available, or may even decide to remove them.
This means there is no guarantee that a new feature will become Generally Available.
A Pre-release feature can be deprecated at any time.

Pre-release features may be disabled by default, and can be enabled via configuration.
Temporal Cloud customers can contact the Temporal account team or [Temporal Support Team](/cloud/support#support-ticket) to gain Pre-release access.

## Public Preview {#public-preview}

**Access:** New features in Public preview are available to everyone.

**Classification:** Features in public preview may undergo further development and testing before they are made Generally Available.
These features are being refined and are recommended for production usage.

**Feedback:** Temporal users are invited to share feedback via the [Community Slack](http://t.mp/slack), by reaching out directly to the Temporal team at product@temporal.io, or by creating issues in the relevant [GitHub repository](https://github.com/temporalio).
Temporal also encourages Temporal Cloud users to submit feedback via [support ticket](/cloud/support#support-ticket).
This feedback will assist in guiding the improvements for General Availability.

**Availability:** New Features in Public Preview may evolve.
The APIs may undergo changes; however, Temporal's goal is to maintain backward compatibility.

## General Availability {#general-availability}

**Access:** Features in General Availability are available to everyone.

**Classification:** The feature is now fully developed, tested, and available for use without further anticipated changes.

**Feedback:** Temporal users are invited to share feedback via the [Community Slack](http://t.mp/slack), by reaching out directly to the Temporal team at product@temporal.io, or by creating issues in the relevant [GitHub repository](https://github.com/temporalio).

**Availability:** Features in General Availability are released with stable APIs and recommended for production use with a committed SLA.

:::info Exceptions

There may be exceptions for different features, but this is the typical expectation.
Any variation will be documented.

:::

---

## Schedules - Temporal feature

Temporal Schedules is a feature that allows you to "schedule" Temporal Workflows at specified times or intervals, adjusting for peak use.

It offers a flexible way to automate and manage your Temporal Workflows, ensuring your business processes run smoothly and efficiently especially when handling time-sensitive tasks.

1. **Automate Repetitive Tasks:**
   Schedules automate repetitive tasks, reducing manual intervention and ensuring timely execution of business processes.
2. **Enhanced Workflow Control and Observability:**
   Gain complete control over your automation processes. With Schedules, you can create, backfill, delete, describe, list, pause, trigger, and update Workflow Executions.
3. **Flexible Timing:**
   Schedule Workflow Executions to run at regular intervals or specific future times, ensuring they execute precisely when needed.
4. **Reliable and Scalable:**
   Designed for reliability and scalability, Temporal Schedules handle the complexities of distributed systems while ensuring your Workflows run as intended, even during failures.
5. **Eliminate External Dependencies:**
   Schedules remove the need to integrate external scheduling systems.

Jump straight to a Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/schedules" text="Schedules using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/schedules" text="Schedules using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/schedules" text="Schedules using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/schedules" text="Schedules using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/schedules" text="Schedules using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/schedules" text="Schedules using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/schedules" text="Schedules using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

---

## Temporal Nexus - Temporal feature

:::tip SUPPORT, STABILITY, and DEPENDENCY INFO

Temporal Nexus is now [Generally Available](/evaluate/development-production-features/release-stages#general-availability) for [Temporal Cloud](/cloud/nexus) and [self-hosted deployments](/production-deployment/self-hosted-guide/nexus).

:::

## Connect Temporal Applications

Nexus allows you to connect Temporal Applications across (and within) isolated Namespaces.
This provides all the benefits of Durable Execution across team and application boundaries with improved modularity, security, debugging, and fault isolation.
Nexus supports cross-team, cross-domain, cross-namespace, multi-region, and multi-cloud use cases.

## Why use Nexus?

Unlike other forms of inter-service communication, Nexus combines a familiar programming model with the resiliency of the Temporal Platform and its queue-based Worker architecture.

### Benefits

- **Integrated Temporal experience** \- with improved security, observability, and reliability.
- **Microservice contracts** \- suitable for sharing across teams or domains.
- **Abstract and share underlying Temporal primitives** \- like Workflows, Signals, or Updates.
- **At-least-once execution guarantees** \- with support for exactly-once execution using Workflow policy.
- **Improved security and blast-radius isolation** \- with separate Namespaces for each team or domain.
- **Modular design** \- for streamlined multi-team development.
- **Custom handlers** \- that execute arbitrary code.
- **No error-prone boilerplate code** \- with Temporal SDK support to build and use Nexus Services.
- **Same queue-based Worker architecture** \- so no bespoke service deployments are needed.

### Use cases

- **Cross-team, cross-domain, and cross-namespace** \-
  Nexus is purpose-built to connect Temporal Applications within and across Namespaces.
  It addresses the limitations of Child Workflows, Activity Wrappers, and bespoke APIs that target a remote Namespace; such as leaking implementation details, second-class observability, overly-permissive security, and error-prone boilerplate code.
  Nexus has a streamlined Temporal developer experience, reliable execution, and integrated observability.

- **Share a subset of a Temporal Application** \-
  Abstract and share a subset of an Application as a Nexus Service.
  Nexus Operations can span any length of execution, be synchronous or asynchronous, and be implemented with Temporal primitives, like Workflows, Signals, or Updates.
  Expose Services on a Nexus Endpoint for others to use and secure them with access control policies.
  Nexus Endpoints decouple callers from handlers, so teams can operate more autonomously.

- **Modular design for growth** \-
  Temporal Nexus enables a modular application design that can evolve as you grow.
  Start with Nexus Services in a monolithic Namespace and move Services to separate Namespaces with small configuration changes.

- **Smaller failure domains** \- When teams operate in the same monolithic Namespace, everything is available to everyone, and mis-behaving Workers can trigger rate limits that affect all teams operating in that monolithic Namespace.
  Nexus enables each team to have their own Namespace for improved security, troubleshooting, and fault isolation.

- **Multi-region** \-
  Nexus requests in Temporal Cloud are routed across a global mTLS-secured Envoy mesh within and across AWS and GCP.
  Built-in Nexus Machinery provides reliable at-least-once execution and Workflow policy can deduplicate requests for exactly-once execution, even across multi-region boundaries.

### Key features

- **Familiar developer experience** \-
  Temporal SDKs provide an integrated way to build and use Nexus Services.
  - Use Nexus Services from a caller Workflow.
  - Run Nexus Service handlers in a Worker, often the same Worker as underlying Temporal primitives.
  - Implement long-running asynchronous Nexus Operations as Workflows.
  - Handle low-latency synchronous Nexus Operations with Temporal primitives or arbitrary code.
  - Execute Operations with at-least-once semantics by default, and exactly-once semantics using Workflow ID reuse policies.

- **Nexus Endpoints with a queue-based Worker architecture** \- Nexus Endpoints are a reverse proxy for Nexus Services.
  - Connect callers and handlers through Nexus Endpoints, for looser coupling.
  - Manage Endpoints in the Nexus Registry using the UI, CLI, or Cloud Ops API.
  - Use a Nexus Endpoint by name, which routes requests to an upstream target Namespace and Task Queue.
  - Handle Nexus requests in a Nexus Worker by polling an Endpoint's target Task Queue, with automatic load balancing.
  - Streamline operations by running Nexus Services in existing queue-based Workers.

- **Built-in Nexus Machinery** \-
  Execution guarantees are provided with built-in Nexus Machinery.
  - Execute Nexus Operations with reliable state-machine-based invocation and completion callbacks.
  - Guarantee atomic handoff from Workflow Event History to Nexus Operation state machines.
  - Ensure reliable execution with automatic retries, rate limiting, concurrency limiting, and circuit breaking.

- **Integrated observability** \-
  Execution debugging and observability is integrated into the Temporal Platform.
  - View Nexus Operation lifecycle and error info in Workflow Event History.
  - Debug across Namespaces with bi-directional linking.
  - Generate metrics, traces, and logs.

- **Improved blast radius isolation** \-
  Separate Namespaces isolate underlying Workers and sensitive Workflow state.
  - Limit direct access to a Namespace, while exposing Nexus Endpoints for others to use.
  - Isolate misbehaving Workers that affect rate limits for all Workers in a Namespace.
  - Avoid leaking Workflow implementation details to external callers.

- **Enhanced security and connectivity** \-
  Temporal Cloud provides integrated Nexus access controls and multi-region routing.
  - Connect Applications across Namespaces in an Account with Temporal's private mTLS-secured Envoy mesh.
  - Multi-region connectivity within and across AWS and GCP.
  - Restrict which callers can use a Nexus Endpoint, with built-in Endpoint access controls.
  - Stream audit logs including Nexus Registry actions to create, update, or delete Endpoints.

## Learn more

To connect with the Nexus community, join the [#nexus](https://temporalio.slack.com/archives/C07LQN0JK9B) channel in [Temporal Slack](https://t.mp/slack).

<RelatedReadContainer>
  <RelatedReadItem path="https://temporal.io/blog/temporal-nexus-now-available" text="Nexus is now generally available - blog post" archetype="blog" />
  <RelatedReadItem path="https://youtu.be/qqc2vsv1mrU?feature=shared&t=2082" text="Nexus keynote & demo - Replay video" archetype="replay-talk" />
  <RelatedReadItem path="https://www.youtube.com/watch?v=izR9dQ_eIe4" text="Nexus deep dive - Replay video" archetype="replay-talk" />
  <RelatedReadItem path="/nexus" text="Nexus concepts and getting started" archetype="encyclopedia" />
  <RelatedReadItem path="/develop/go/nexus" text="Go SDK - Nexus quick start and code sample" archetype="feature-guide" />
  <RelatedReadItem path="/develop/java/nexus" text="Java SDK - Nexus quick start and code sample" archetype="feature-guide" />
  <RelatedReadItem path="/cloud/nexus" text="Production deployment in Temporal Cloud" archetype="feature-guide" />
  <RelatedReadItem path="/production-deployment/self-hosted-guide/nexus" text="Self-hosted deployment" archetype="feature-guide" />
</RelatedReadContainer>

---

## Temporal Testing Suite - Temporal feature

In the context of Temporal, you can create these types of automated tests:

1. End-to-end: Running a Temporal Server and Worker with all its Workflows and Activities; starting and interacting with Workflows from a Client.
2. Integration: Anything between end-to-end and unit testing.
   Running Activities with mocked Context and other SDK imports (and usually network requests).
   Running Workers with mock Activities, and using a Client to start Workflows.
   Running Workflows with mocked SDK imports.
3. Unit: Running a piece of Workflow or Activity code and mocking any code it calls.

Jump straight to a Temporal SDK feature guide.

<RelatedReadContainer>
    <RelatedReadItem path="/develop/go/testing-suite" text="Testing using the Go SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/java/testing-suite" text="Testing using the Java SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/php/testing-suite" text="Testing using the PHP SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/python/testing-suite" text="Testing using the Python SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/typescript/testing-suite" text="Testing using the TypeScript SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/dotnet/testing-suite" text="Testing using the .NET SDK" archetype="feature-guide" />
    <RelatedReadItem path="/develop/ruby/testing-suite" text="Testing using the Ruby SDK" archetype="feature-guide" />
</RelatedReadContainer>

---

## Child Workflows - Temporal feature

In Temporal, **Child Workflows** enable applications to achieve another level of composability when it comes to throughput.

The following example scenarios are a few reasons to use this feature:

- To create a separate service that can be invoked from multiple other services or applications.
- To partition a step into smaller chunks.
- To manage a dedicated resource and guarantee uniqueness.
- To execute logic periodically without overwhelming the parent business process.

See the SDK feature guides for implementation details:

<RelatedReadContainer>
  <RelatedReadItem path="/develop/go/child-workflows" text="Go SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/java/child-workflows" text="Java SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/php/child-workflows" text="PHP SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/python/child-workflows" text="Python SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/typescript/child-workflows" text="TypeScript SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/dotnet/child-workflows" text=".NET SDK Child Workflow feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/ruby/child-workflows" text="Ruby SDK Child Workflow feature guide" archetype="feature-guide" />
</RelatedReadContainer>

For a deep dive into Child Workflows see the [Child Workflows Encyclopedia page](/child-workflows).

---

## Workflow message passing - Temporal feature

Need to interact with your Workflow from outside of it? Think about use cases like these:

- Your shipment-tracking Workflow needs to know when the item leaves the warehouse and is loaded into their truck. **Signal** your Workflow when the truck driver scans the barcode.
- Folks in your company want to track the progress of their data migration Workflows. **Query** your running batch Workflow to get the data for the progress bar.
- Your eCommerce shopping cart Workflow needs to know when a new item is added. **Update** it to add the item and receive back the current items to render.

Temporal provides Signals, Queries, and Updates to allow rich interactivity with your running Workflows.

**Signals**: Signal to send messages asynchronously to a running Workflow, changing its state or controlling its flow in real-time.

**Queries**: Query to check the progress of your Workflow or debug the internal state in real-time.

**Updates**: Update to send synchronous requests to your Workflow and track it in real-time.

To learn more about using these powerful primitives, see our encyclopedia Entry:

<RelatedReadContainer>
  <RelatedReadItem path="/encyclopedia/workflow-message-passing" text="Workflow message passing (Signals, Queries, & Updates)" archetype="encyclopedia" />
</RelatedReadContainer>

For a deeper dive into Workflow message passing, enroll in one of [our courses](https://learn.temporal.io/courses/interacting_with_workflows).

If you want to jump to straight to implementation details, see the SDK feature guides.

<RelatedReadContainer>
  <RelatedReadItem path="/develop/go/message-passing" text="Go SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/java/message-passing" text="Java SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/python/message-passing" text="Python SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/typescript/message-passing" text="TypeScript SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/php/message-passing" text="PHP SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/dotnet/message-passing" text=".NET SDK Workflow message passing feature guide" archetype="feature-guide" />
  <RelatedReadItem path="/develop/ruby/message-passing" text="Ruby SDK Workflow message passing feature guide" archetype="feature-guide" />
</RelatedReadContainer>

---

## Evaluate Temporal

Temporal is designed to make developing distributed applications a delightful experience.
Developers benefit from a clear approach to structure their code and visibility into the state of their application.
Applications benefit from fault-tolerance and execution guarantees.
Thousands of companies of all sizes are leveraging Temporal's capabilities for both mission critical and standard workloads.

- [Why Temporal](/evaluate/why-temporal)
- [Development and production features](/evaluate/development-production-features)
- [Use cases](/evaluate/use-cases-design-patterns)
- [Temporal Cloud](/cloud)
- [Security](/security)

---

## Temporal Cloud Actions

Actions track both the progress of a workflow (such as Workflow Start, Schedule Started, Workflow reset) and broader capabilities
enabled by Temporal Cloud.

Temporal Cloud Actions are the primary unit of consumption-based pricing for Temporal Cloud.
They track billable operations within the Temporal Cloud Service, such as starting Workflows, recording a Heartbeat, or sending messages.

The following result in an action on Temporal Cloud:

## Workflows

- **Workflow started**.
  Occurs via client start, [Continue-As-New](/workflow-execution/continue-as-new), [Child Workflow](/child-workflows) start.
  If a Workflow start fails, an Action is not recorded.
  De-duplicated Workflow starts that share a Workflow ID do _not_ count as an Action.
- **Workflow reset**.
  Occurs when a [Workflow](/workflows) is reset.
  (Actions that occur before a [Reset](/workflow-execution/event#reset) are counted even if they are no longer visible in [Event History](/workflow-execution/event#event-history).)
- **Timer started**.
  Includes implicit Timers that are started by a Temporal SDK when timeouts are set, such as `AwaitWithTimeout` in Go or `condition` in TypeScript.
- **Search Attribute upsert requested**.
  Occurs for each invocation of `UpsertSearchAttributes` command.
  Multiple Search Attributes updated in a single `UpsertSearchAttributes` command count as one Action.
  Search Attributes specified during Workflow start are _excluded_ from Action counts.
  The `TemporalChangeVersion` Search Attribute, used for Workflow versioning, is also exempt from Action counting.
- **Signal sent**.
  An Action occurs for every [Signal](/sending-messages#sending-signals), whether sent from a Client or from a Workflow. Also, one total action occurs for any [Signal-With-Start](/sending-messages#signal-with-start), regardless of whether the Workflow starts.
- **Query received by Worker**.
  An Action occurs for every [Query](/sending-messages#sending-queries), including viewing the call stack in the Temporal Cloud UI, which results in a Query behind the scenes.
- **Update received by Worker**.
  An Action occurs for every successful [Update](/sending-messages#sending-updates) and every [rejected](/handling-messages#update-validators) Update. This includes [Update-With-Start](/sending-messages#update-with-start), and is in addition to the start Action in the case when the Workflow starts as well.
  De-duplicated Updates that share an Update ID do _not_ count as an Action.
- **Side Effect recorded**.
  For a mutable [Side Effect](/workflow-execution/event#side-effect), an Action occurs only when the value changes.
- **Workflow Execution Options updated.** An Action occurs for every [Workflow-Execution-Options-Updated](/references/events#workflowexecutionoptionsupdated) event.
  This includes attaching a Workflow completion callback or modifying a Workflow versioning override.

## Child Workflows

- **Start Child Workflow** and **Child Workflow Execution**.
  When the parent Workflow durably records the intent to start a Child Workflow, it results in two Actions,
  one for starting the Workflow, and another for the attempted Execution.

## Activities

- **Activity started or retried**.
  Occurs each time an Activity is started or retried.
- **Local Activity started**.
  All [Local Activities](/local-activity) associated with one Workflow Task count as a single Action.
  That's because Temporal Cloud counts all [RecordMarkers](/references/commands#recordmarker) from each Workflow Task as one action, and not _N_ actions.
  Please note:
  - Each additional Workflow Task heartbeat after counts as an additional Action.
  - Local Activities retried following a Workflow Task heartbeat count as one Action (capped at 100 Actions).
- **Activity Heartbeat recorded**.
  A Heartbeat call from Activity code counts as an Action only if it reaches the [Temporal Server](/temporal-service/temporal-server).
  Temporal SDKs throttle [Activity Heartbeats](/encyclopedia/detecting-activity-failures#activity-heartbeat).
  The default throttle is 80% of the [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout).
  Heartbeats don't apply to Local Activities.

## Schedules

[Schedules](/schedule) allows you to schedule a Workflow to start at a particular time.
Each execution of a Schedule accrues three actions:

- **Schedule Start**.
  This accounts for two actions.
- **Workflow started**.
  This is a single action to start the target Workflow.
  It includes initial Search Attributes as part of the start request.

## Export

[Workflow History Export](/cloud/export) enables you to export closed Workflow Histories to a cloud storage sink of your choice.

- **Workflow exported**.
  Each Workflow exported accrues a single action.
- Excluded from APS calculations.

## Temporal Nexus

- For [Nexus Operation scheduled](/references/events#nexusoperationscheduled), the caller Workflow starting a Nexus Operation results in one Action on the caller Namespace.
- For [Nexus Operation canceled](/references/events#nexusoperationcanceled), the caller Workflow canceling a Nexus Operation results in one Action on the caller Namespace.
- The underlying Temporal primitives (such as Workflows, Activities, and Signals) created by a Nexus Operation handler (directly or indirectly) result in the normal Actions for those primitives billed to the handler’s Namespace.
  This includes retries for underlying Temporal primitives like Activities but _not_ for handling the Nexus Operation itself or a retry of the Nexus Operation itself.

## Capacity

- For Namespace Capacity Temporal Resource Units (TRUs), Actions are generated up to the included hourly allocation for TRUs in any hour where TRUs are set and actual usage falls beneath the included hourly Action allocation.
- Excluded from APS calculations.

## Usage

Actions usage is tracked across an account in the [usage dashboard](https://cloud.temporal.io/usage) and is visible to Account Owners, Finance Admin and Global Admin.
For individual namespaces, usage can be seen in the [namespace summary](https://cloud.temporal.io/namespaces/) for a specific namespace.

![Temporal Cloud Usage dashboard](/img/cloud/billing/usage-dashboard.png)

## Actions in Workflows

When viewing a Workflow history, events that represent a Billable Action are annotated with the number consumed by the event in
the **Billable Actions** Column. These Actions are summarized at the top of the workflow.

![Temporal Cloud Usage dashboard showing aggregated Billable Actions](/img/cloud/billing/aggregate-billable-actions.png)

![Temporal Cloud Usage dashboard showing individual Billable Actions associated with events](/img/cloud/billing/individual-billable-actions.png)

This Billable Action estimate is useful for projecting the cost of workflows.
For example, if you ran a test workflow that generated 20 Billable Actions and projected that it would be run 100 times
a day for a month, you could anticipate that workflow to generate 20 Actions x 100 runs/day x 30 days = 60,000 Billable Actions per month.
You can also use the Billable Action estimate to help optimize workflows by better understanding your cost drivers.

:::tip Excluded Billable Actions

The Billable Action estimate is an experimental feature and only measures Billable Actions that exist within workflow event histories.
Some billable concepts are not included in these calculations such as:

- Query
- Activity Heartbeats
- Rejected Update Workflow Executions
- Export
- Schedule

Additionally, Workflows with the `TemporalNamespaceDivision` Search Attribute set may not have accurate Billable Action Estimates.
The estimated Billable Actions should only be treated as an estimate.
If billable events exist outside of event history, the Actions count could be higher.

:::

[Reach out](https://pages.temporal.io/contact-us) to our team for more information or to help size your number of Actions.

---

## System limits - Temporal Cloud

Temporal Cloud enforces a variety of limits to keep the service reliable, including rate limits (how often something may occur in a unit of time), resource limits (how many of a given resource may exist at any one time), and configuration limits (minimum or maximum values for a setting)

Every limit applies at a specific scope (level of the application):

- At the Temporal Cloud [Account level](#account-level)
- At the [Namespace level](#namespace-level)
- At the [Nexus endpoint level](#nexus-endpoint-level)
- Within the [programming model](#programming-model-level) itself

## Account level

The following limits apply at the Temporal Cloud Account level (per account).

### Users

- Scope: Account
- Default limit: 300 users
- How to increase: [Contact support](/cloud/support#support-ticket) 

### Namespaces

- Scope: Account
- Default limit: 10 namespaces
- How to increase: 
  - Automatically increased as you start creating namespaces, up to a limit of 100.
  - [Contact support](/cloud/support#support-ticket)

## Namespace level

The following limits apply at the Namespace level.

### Actions per second

- Scope: Namespace
- Default limit: 500 actions per second (APS)
- How to increase:
  - Automatically increases (and decreases) based on the last 7 days of APS usage. Will never go below the default limit.
  - See [Capacity Modes](/cloud/capacity-modes).
  - [Contact support](/cloud/support#support-ticket).

See the [Actions page](/cloud/actions) for the list of actions. 

### Requests per second

- Scope: Namespace
- Default limit: 2000 requests per second (RPS)
- How to increase:
  - Automatically increases (and decreases) based on the last 7 days of RPS usage. Will never go below the default limit.
  - See [Capacity Modes](/cloud/capacity-modes).
  - [Contact support](/cloud/support#support-ticket).

See the [glossary](/glossary#requests-per-second-rps) for more about RPS.

### Operations per second

- Scope: Namespace
- Default limit: 4000 operations per second (OPS)
- How to increase:
  - Automatically increases (and decreases) based on the last 7 days of OPS usage. Will never go below the default limit.
  - See [Capacity Modes](/cloud/capacity-modes).
  - [Contact support](/cloud/support#support-ticket).

See the [operations list](/references/operation-list) for the list of operations.

### Schedules rate limit

- Scope: Namespace
- Default limit: 10 schedule requests per second (RPS)
- How to increase: [Contact support](/cloud/support#support-ticket)

To avoid throttling, don't schedule all your Workflow Executions to start at the same time (daily, weekly, monthly, etc.).
Every Temporal SDK supports jittering, which adds small random delays to Schedule specifications, helping to reduce load at any specific moment.
Set the `jitter` value to the largest delay you will permit before your Workflow Execution must begin.
This approach uniformly distributes the scheduled Workflow Execution launches through that period and reduces your Schedule Workflow Execution RPS load.

### Visibility API Rate Limit

- Scope: Namespace
- Default limit: 30 Visibility API calls per second
- Not configurable

All read calls are subject to the Visibility API rate limit.

### Nexus Rate Limit {#nexus-rate-limits}

Nexus requests (such as starting a Nexus Operation or sending a Nexus completion callback) are counted as part of the overall Namespace RPS limit.
If too many Nexus requests are sent at once, they may be throttled, along with other requests to the Namespace.
Throttling limits the rate at which Nexus requests are processed, ensuring the RPS limit isn't exceeded.

You can request this limit be manually raised by [opening a support ticket](https://docs.temporal.io/cloud/support#support-ticket).

:::note

For the target Namespace of a Nexus Endpoint, even though there are no Action results for handling a Nexus Operation itself, the Nexus requests on a target Namespace do count towards the overall RPS limit for the Namespace as a whole.

:::

### Certificates

Temporal Cloud limits each Namespace to a total of 32 KB or 16 certificates, whichever is reached first.

### Concurrent Task pollers

Temporal Cloud limits each Namespace to 20,000 Activity pollers and 20,000 Workflow Task pollers concurrently. 

Each SDK offers a way to configure Workers for per-Worker maximum Activity and Workflow Task pollers.
Those values do not affect the global Namespace limit.

### Default Retention Period

The [Retention Period](/temporal-service/temporal-server#retention-period) is set per Namespace.

Temporal Cloud sets the default Retention Period to 30 days.
This is configurable in the Temporal Web UI.

[Navigate to your list of Namespaces](https://cloud.temporal.io/namespaces), choose the Namespace you want to update, and select edit:

<CaptionedImage
    src="/img/cloud/cloud-guide/edit-namespace-option.png"
    title="Choose your Namespace and select Edit"
/>

<CaptionedImage
    src="/img/cloud/cloud-guide/edit-retention-period.png"
    title="Update the Retention Period"
/>

You can set the Retention Period between 1 and 90 days.

### Batch jobs

A Namespace can have just one [Batch job](/cli/batch) running at a time.

Each batch job operates on a maximum of 50 Workflow Executions per second.

### Number of Custom Search Attributes

There is a limit to the number of custom Search Attributes per attribute type per Namespace:

| Search Attribute type | Limit |
| --------------------- | ----- |
| Bool                  | 20    |
| Datetime              | 20    |
| Double                | 20    |
| Int                   | 20    |
| Keyword               | 40    |
| KeywordList           | 5     |
| Text                  | 5     |

### Custom Search Attribute names

When creating custom Search Attributes in Temporal Cloud, the attribute names must adhere to the following constraints:

- Maximum characters: 64
- Allowed characters: `[a-zA-Z0-9.,:-_\/@ ]`.

For more information on custom Search Attributes see [Custom Search Attributes limits](/search-attribute#custom-search-attribute).

## Nexus Endpoint level

### Nexus Endpoints limits

By default, each account is provisioned with 100 Nexus Endpoints.
You can request further increases beyond the initial 100 Endpoint limit by [opening a support ticket](/cloud/support#support-ticket).

## Programming model level

The following limits apply at the programming model level.
See also: [Self-hosted Temporal Service defaults](/self-hosted-guide/defaults).

### Identifier length limit

Identifiers, such as Workflow Id, Workflow Type, and Task Queue names, are limited to a maximum length of 1,000 bytes.
Note that Unicode characters may use multiple bytes.

### Per message gRPC limit

Each gRPC message received has a limit of 4 MB.
This limit applies to all gRPC endpoints across the Temporal Platform.

### Event History transaction size limit

An Event History transaction encompasses a set of operations such as initiating a new Workflow, scheduling an Activity, processing a Signal, or starting a Child Workflow.
These operations create Events that are then logged in the Event History.
The transaction size limit restricts the total size of Events that can be accommodated within a single transaction.

The size limit for any given [Event History](/workflow-execution/event#event-history) transaction is 4 MB.
This limit is non-configurable for Temporal Cloud.

### Transaction Payload size limit

Blob size limit for Payloads, including Workflow context and each Workflow and Activity argument and return value:
  - The max payload for a single request is 2 MB.
  - The max size limit for any given [Event History](/workflow-execution/event#event-history) transaction is 4 MB.

This limit is non-configurable for Temporal Cloud.

The [BlobSizeLimitError guide](/troubleshooting/blob-size-limit-error) provides solutions for handling large payloads.

### Per Workflow Execution concurrency limits

If a Workflow Execution has 2,000 incomplete Activities, Signals, Child Workflows, or external Workflow Cancellation requests, additional [Commands](/workflow-execution#command) of that type will fail to be applied to that Workflow Execution:

- `ScheduleActivityTask`
- `SignalExternalWorkflowExecution`
- `StartChildWorkflowExecution`
- `RequestCancelExternalWorkflowExecution`

For optimal performance, limit concurrent operations to 500 or fewer.
This reduces Workflow's Event History size and decreases the loading time in the Web UI.

### Per Workflow Execution Signal limit

A single Workflow Execution may receive up to 10,000 Signals.
After that limit is reached, no more Signals will be processed for that Workflow Execution.

### Per Workflow Execution Update limits

A single Workflow Execution can have a maximum of 10 in-flight Updates and 2000 total Updates in History.

### Workflow Execution Event History limits

As a precautionary measure, a Workflow Execution's Event History is limited to 51,200 Events or 50 MB.
It warns you after 10,240 Events or 10 MB.
This limit applies to all Temporal Workflow Executions, whether on Temporal Cloud or other deployments.

This limit is non-configurable for Temporal Cloud.

Read more about [Temporal Workflow Execution limits](/workflow-execution/limits) on the [Temporal Workflow](/workflows) documentation page.

### Per Workflow Callback limits

A single Workflow Execution can have a maximum of 32 total Callbacks.

These limits may be exceeded when [multiple Nexus callers attach to the same handler Workflow](/nexus/operations#attaching-multiple-nexus-callers).

See the Nexus Encyclopedia entry for [additional details](/workflow-execution/limits#workflow-execution-callback-limits).

### Per Workflow Nexus Operation limits {#per-workflow-nexus-operation-limits}

A single Workflow Execution can have a maximum of 30 in-flight Nexus Operations.

See the Nexus Encyclopedia entry for [additional details](/workflow-execution/limits#workflow-execution-nexus-operation-limits).

### Nexus Operation request timeout {#nexus-operation-request-timeout}

Less than 10 seconds is the maximum duration for a Nexus handler to process a single Nexus start or cancel request.

The timeout is measured from the calling History Service and the request must go through matching, so the available time for a handler to respond is often much less than 10 seconds.
Handlers should observe the context deadline and ensure they don't exceed it.
This includes fully processing a synchronous Nexus operation and starting an asynchronous Nexus operation, for example one that starts a Workflow.

If a Nexus handler doesn’t process a start or cancel request within 10 seconds, it will receive a context deadline exceeded error, and the caller will retry, with an exponential backoff, for the ScheduleToClose duration for the overall Nexus Operation.
This has a default and maximum as defined below in [Nexus Operation duration limits](/cloud/limits#nexus-operation-duration-limits).

### Nexus Operation duration limits {#nexus-operation-duration-limits}

Each Nexus Operation has a maximum ScheduleToClose duration of 60 days.
This is most applicable to asynchronous Nexus Operations completed with an asynchronous callback using a separate Nexus request from the handler back to the caller Namespace.

For enhanced security, you may sign completion callbacks with a single-use token in the future, and the 60 day maximum allows you to rotate the asymmetric encryption keys used for completion callback request signing.

While the caller of a Nexus Operation can configure the ScheduleToClose duration to be shorter than 60 days, the maximum duration can not extend beyond 60 days and capped by the server to 60 days.

### Timer duration limit

Timers have a maximum duration of 100 years in Temporal Cloud.

## Worker Versioning level

### Max Worker deployments limits {#max-worker-deployments-limits}

The maximum number of Worker deployments that the server allows to be registered in a single Namespace. Defaults to 100.

### Max versions in deployment limits {#max-versions-in-deployment-limits}

The maximum number of versions that the server allows to be registered in a single Worker deployments at a given time. Note that unused versions will be deleted by the system automatically when this limit is reached. Defaults to 100.

### Max Task Queues In Deployment Version limits {#max-task-queues-in-deployment-version-limits}

The maximum number of Task Queues that the server allows to be registered in a single Worker Deployment Version. Defaults to 100.

---

## Overview - Temporal Cloud

Temporal Cloud is a fully managed durable execution platform.
It handles the complexity of running Temporal at scale—persistence, replication, upgrades, and availability—so you can focus on building applications.

Your code runs in your environment.
Temporal Cloud never sees your application logic or sensitive data.
The platform stores encrypted Workflow state and orchestrates execution, while your Workers execute business logic wherever you deploy them.

## How Temporal Cloud works

Temporal Cloud operates as the control plane for your distributed applications:

1. **Your environment**: You run Workers that execute your Workflow and Activity code. These can be deployed anywhere—Kubernetes, VMs, serverless, on-premises.
2. **Temporal Cloud**: Manages Workflow state, Event History, task queuing, and scheduling. All data is encrypted in transit and at rest.
3. **Temporal SDKs**: Your applications use the SDK to communicate with Temporal Cloud over secure gRPC connections.

This separation means Temporal Cloud scales independently of your application.
You control compute resources for your Workers; Temporal handles the orchestration layer.

## Architecture

### Cell-based infrastructure

Temporal Cloud uses a cell-based architecture to achieve isolation and scalability.
Each cell is a self-contained deployment unit with its own:

- Dedicated cloud account and VPC
- Kubernetes cluster running Temporal services
- Primary database with synchronous replication across three availability zones
- Elasticsearch for Workflow visibility and search
- Load balancers and ingress management
- Observability and certificate infrastructure

Cells act as failure domains.
If infrastructure within a cell experiences issues, only Namespaces in that cell are affected.
This design limits blast radius and enables independent scaling.

### Data plane and control plane

**Data plane**: Where your Workflows execute. Each cell processes Workflow operations, persists state, and manages task queues. The data plane is optimized for low latency and high throughput.

**Control plane**: Manages provisioning, configuration, and lifecycle operations. When you create a Namespace, the control plane:
1. Selects an appropriate cell in your chosen region
2. Provisions database resources and roles
3. Generates and deploys mTLS certificates
4. Configures ingress routes and validates connectivity

The control plane uses Temporal itself (durable execution) to orchestrate these operations reliably.

### Multi-cloud availability

Temporal Cloud runs on both AWS and GCP:

- **14 AWS regions** spanning North America, Europe, Asia Pacific, and South America
- **5 GCP regions** in North America, Europe, and Asia Pacific

You can create Namespaces in any supported region.
For disaster recovery, you can replicate across regions within a cloud provider or across cloud providers entirely.

See [Service regions](/cloud/regions) for the complete list of available regions.

## Built-in reliability

Every Temporal Cloud Namespace includes baseline high availability:

- **Three-zone replication**: Workflow state synchronously replicates across three availability zones before acknowledging writes
- **Automatic failover**: If one zone becomes unavailable, operations continue on the remaining zones
- **99.9% SLA**: Contractual uptime guarantee for standard Namespaces

### High Availability features

For workloads requiring stronger guarantees, Temporal Cloud offers three replication options:

| Deployment | Description | Use case |
|------------|-------------|----------|
| **Same-region** | Replicate across isolated cells within one region | Single-region applications needing cell-level isolation |
| **Multi-region** | Replicate across regions within one cloud provider | Geographic redundancy and compliance requirements |
| **Multi-cloud** | Replicate across cloud providers (AWS ↔ GCP) | Maximum resilience against provider-level outages |

High Availability Namespaces include:
- **99.99% SLA**: Four-nines contractual uptime guarantee
- **Sub-1-minute RPO**: Recovery Point Objective for data loss
- **20-minute RTO**: Recovery Time Objective for failover completion
- **Automatic or manual failover**: Choose your preferred failover strategy

See [High Availability](/cloud/high-availability) for configuration details.

## Security model

Temporal Cloud implements defense-in-depth security:

### Your code stays with you

Temporal Cloud never executes your application code.
Workers run in your environment, connecting to Temporal Cloud over encrypted channels.
You control access to your compute resources and secrets.

### Client-side encryption

The [Data Converter](/dataconversion) lets you encrypt payloads before they leave your Workers.
Temporal Cloud stores ciphertext—if the service were compromised, your data remains encrypted.
Deploy a [Codec Server](/production-deployment/data-encryption) to decrypt data in the Web UI without sharing keys.

### Network isolation

- **mTLS authentication**: Per-Namespace certificate-based authentication for gRPC endpoints
- **API key authentication**: Alternative to certificates for simpler key management
- **Private connectivity**: AWS PrivateLink and GCP Private Service Connect for traffic that never traverses the public internet

### Compliance

Temporal Technologies maintains SOC 2 Type 2 certification and complies with GDPR and HIPAA regulations.
Audit logs capture all API operations and can be exported to your security monitoring systems.

See [Security model](/cloud/security) for complete details.

## Consumption-based pricing

Temporal Cloud charges based on what you use:

### Actions

The primary billing unit.
Actions are billable operations like starting Workflows, sending Signals, recording Heartbeats, and completing Activities.
Pricing starts at $50 per million Actions with volume discounts as you scale.

### Storage

- **Active Storage**: Event History for running Workflows
- **Retained Storage**: Event History for completed Workflows (configurable retention period up to 90 days)

### Plans

Four tiers—Essentials, Business, Enterprise, and Mission Critical—with increasing support levels, included Actions/Storage, and features like SAML and SCIM.
The Essentials plan starts at $100/month.

Self-serve signup and plan management available at [cloud.temporal.io](https://cloud.temporal.io).

See [Pricing](/cloud/pricing) for detailed rates and examples.

## Portability

Temporal Cloud runs the same Temporal Server as the open-source distribution.
This means:

### Zero code changes

Applications built for self-hosted Temporal work on Temporal Cloud without modification.
Update your connection configuration to point at your Cloud Namespace—that's it.

### Zero-downtime migration

[Automated migration](/cloud/migrate/automated) uses Workflow replication to move running Workflows from self-hosted to Cloud (or between Cloud regions) without interruption.
No Workflow restarts, no data loss, no downtime.

[Manual migration](/cloud/migrate/manual) works by updating Clients and Workers to use new Namespace endpoints while existing Workflows complete naturally.

### Bidirectional

Move workloads from self-hosted to Cloud, Cloud to self-hosted, or between Cloud regions and providers.
The same migration tooling works in any direction.

## Self-serve operations

Temporal Cloud is designed for self-service:

- **Web UI**: Create Namespaces, manage users, configure settings at [cloud.temporal.io](https://cloud.temporal.io)
- **CLI (`tcld`)**: Automate operations from the command line
- **Terraform provider**: Infrastructure-as-code for Namespaces, users, and configuration
- **Cloud Ops API**: Programmatic access for custom tooling and automation

No support tickets required for standard operations.

## Getting started

1. [Sign up for Temporal Cloud](https://temporal.io/get-cloud)
2. [Create your first Namespace](/cloud/namespaces)
3. [Connect your Workers](/cloud/get-started#set-up-your-clients-and-workers)
4. [Run your first Workflow](/cloud/get-started#run-your-first-workflow)

For existing Temporal users, see [Migration](/cloud/migrate) to move self-hosted workloads to Cloud.

---

## Temporal Cloud pricing

Temporal Cloud is a consumption-based service.
You pay only for what you use.
Our pricing reflects your use of [_Actions_](#action), [_Storage_](#storage), and [_Support_](/cloud/support#support).
It is flexible, transparent, and predictable, so you know your costs.

This page describes the elements of Temporal Cloud pricing.
It gives you the information you need to understand and estimate costs for your implementation.
For more exact estimates, please reach out to [our team](https://pages.temporal.io/ask-an-expert).

Billing and cost information is available directly in the Temporal Cloud UI.
For more information, visit the [Billing and Cost](/cloud/billing-and-cost) page.

## Temporal Cloud pricing model {#pricing-model}

This section explains the basis of the Temporal Cloud pricing model and how it works.
Your total invoice each calendar month is the combination of Temporal Cloud consumption ([Actions](#action) and [Storage](#storage)), and a [Temporal Cloud Plan](#base_plans) that includes [Support](/cloud/support#support).

### Temporal Cloud Plans {#base_plans}

**How plans work**

Each Temporal Cloud account includes a plan with Support, Actions, Active Storage, Retained Storage and platform features.
Base allocations help you get started with the Temporal platform, so you can better estimate costs.

- Temporal Cloud Plans are charged monthly.
- Action and Storage allocations are reset each calendar month.

Temporal offers four plans: Essential, Business, Enterprise, Mission Critical.
Prices are outlined in the following table:

|                   | Essentials                                                                     | Business                                                                                                                          | Enterprise                                                                                                                                                 | Mission Critical                                                                                                                                           |
| ----------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Support Targeting | Basic use                                                                      | Production deploymentsthat scale                                                                                            | Enterprise deploymentsw/ stringent uptime demands                                                                                                     | Mission-critical applicationsw/ the highest support needs                                                                                            |
| Support Features  | Access to Support                                                              | P0 Response Times                                                                                                        | P0: \<30 Min, 24/7Private Slack                                                                                                          | P0: \<15 Min, 24/7Private SlackDedicated DSE                                                                                    |
| Product Features  | 1M Actions1 GB Active Storage40 GB Retained Storage | Commit discountsSAML includedSCIM (Add-on)2.5M Actions2.5 GB Active Storage100 GB Retained Storage | Commit discountsSAML includedSCIM included10M Actions10 GB Active Storage400 GB Retained Storage | Commit discountsSAML includedSCIM included10M Actions10 GB Active Storage400 GB Retained Storage |
| Plan Pricing      | Greater of&#36;100/mo or5% of Usage Spend                    | Greater of&#36;500/mo or10% of Usage Spend                                                                      | Priced annually: [contact Sales](mailto:sales@temporal.io) for details                                                                               | Priced annually: [contact Sales](mailto:sales@temporal.io) for details                                                                               |
| Usage Pricing     | [Pay-As-You-Go](#payg) Pricing                                                 | Choose from  [Pay-As-You-Go](#payg) or [Commitment Pricing](#commitment-pricing)                                            | Choose from  [Pay-As-You-Go](#payg) or [Commitment Pricing](#commitment-pricing)                                                                     | Choose from  [Pay-As-You-Go](#payg) or [Commitment Pricing](#commitment-pricing)                                                                     |

Please note, partial months are prorated to the day.
Find a complete description of Support offerings and response times in our [Support](/cloud/support) documentation.

:::note Converting GB to GBH

Active and Retained Storage allocations are translated into GBh at a rate of 1GB equals 744GBh.

:::

### Actions {#action}

**What are Temporal Actions?**

Actions are the primary unit of consumption-based pricing for Temporal Cloud.
They track billable operations within the Temporal Cloud Service, such as starting Workflows, recording a Heartbeat or sending messages.
**Specific Billable Actions are discussed on the [Actions](/cloud/actions) page.**

[Reach out](https://pages.temporal.io/contact-us) to our team for more information or to help size your number of Actions.

### Storage {#storage}

**How Workflow Storage works**

A Workflow's execution might exist for a few seconds, a day, month, or even forever.
The Temporal Service stores the Workflow Execution's [Event History](/workflow-execution/event#event-history).
Under this framework, a Workflow Execution has only two states, open (Active Storage) or closed (Retained Storage).

- _Active Storage_ measures the amount of storage used by active Workflows.

- When the execution of a Workflow finishes, Temporal Cloud stores Event History for a defined [Retention Period](/temporal-service/temporal-server#retention-period), which is set by the user per Namespace.
  This is _Retained Storage_.
  Typical uses of Retained Storage include compliance, debugging, workload refresh, and business analytics.
  When closed Workflow Histories need to be retained for more than the 90-day maximum period on Temporal Cloud, we recommend using our [**Export**](/cloud/export) feature.

Storage costs are measured in gigabyte-hours (GBh).

### Pricing options {#pricing-options}

**How to Pay for Temporal Cloud**

After you exceed your Actions and Storage allocations in your base tier, Temporal Cloud offers two payment options: Pay-As-You-Go and Commitments.
Both models meter and bill for three primary components: [Actions](#action), [Storage](#storage), and [your Temporal Cloud Plan](/cloud/support#support).

- With Pay-As-You-Go, you are invoiced each calendar month based on your consumption.
  Pay-As-You-Go pricing automatically applies volume prices as your Actions scale.
- With Commitments, you pre-purchase your Temporal Cloud spend with Temporal Credits.
  Temporal Credits pay for your Temporal Cloud consumption, including Temporal Cloud Plan charges.

## Pay-As-You-Go {#payg}

**How does Pay-As-You-Go pricing work?**

Pay-As-You-Go pricing is based on consumption.
This section explains how you're billed each calendar month and gives examples.

### Action pricing {#payg-action-pricing}

Actions pricing starts at &#36;50 per million Actions (&#36;0.00005 per Action).
You gain progressive volume discounts as you scale.
Discounts are based on your account's total usage, metered and billed for each calendar month:

| Actions               | Price per Million Actions                                                                 |
| --------------------- | ----------------------------------------------------------------------------------------- |
| First 5M              | &#36;50                                                                                   |
| Next 5M, up to 10M    | &#36;45                                                                                   |
| Next 10M, up to 20M   | &#36;40                                                                                   |
| Next 30M, up to 50M   | &#36;35                                                                                   |
| Next 50M, up to 100M  | &#36;30                                                                                   |
| Next 100M, up to 200M | &#36;25                                                                                   |
| Over 200M             | Contact [Sales](mailto:sales@temporal.io) for info _More discounts, helpful humans_ |

**Example**

If you consume 11.25M Actions in excess of your Temporal Cloud Plan allocation in one calendar month, your bill for Actions will be:

```
5M Actions ⨉ $50 Per Million Actions = $250
5M Actions ⨉ $45 Per Million Actions = $225
1.25M Actions ⨉ $40 Per Million Actions = $50
Actions
$250 (First Tier) + $225 (Second Tier) + $50 (Third Tier) = $525
```

### Storage pricing {#payg-storage-pricing}

Most accounts’ storage needs are met by our Temporal Cloud Plans.
For additional storage within a calendar month, you are billed for Active and Retained Storage as follows:
| **Storage** | **Price per GBh (USD)** |
| ----------- | ----------------------- |
| Retained | &#36;0.00105 |
| Active | &#36;0.042 |

:::tip Storage costs are also affected by Temporal System Workflows that back features such as:

- [Schedules](https://docs.temporal.io/schedule): Each Scheduled Workflow contributes to storage usage. Supplied inputs, outputs, and failures all account for the storage usage incurred from Scheduled Workflows.
- [Batch jobs](https://docs.temporal.io/cli/batch): Batch Workflow executions also consume storage.

These Workflow executions contribute to overall active and retained storage consumption.

:::

**Example**

If you have 720 GBh of Active Storage and 3,600 GBh of Retained Storage in excess of your Base Tier allocations in one calendar month, your bill will be:

```
720 GBh Active Storage ⨉ $0.042 per GBh = $30.24
3,600 GBh Retained Storage ⨉ $0.00105 per GBh = $3.78
Total Storage Bill: $30.24 Active Storage + $3.78 Retained Storage = $34.02
```

## Temporal Cloud Plan pricing

Your Temporal Cloud Plan pricing is the greater of the minimum monthly price or a percent (%) of your consumption spend:

- The Essentials tier is priced at the greater of &#36;100/month or 5% of your Temporal Cloud consumption.
- The Business tier is priced at the greater of &#36;500/month or 10% of Temporal Cloud consumption.
- The Enterprise and Mission Critical Support plans must be paid annually. Contact [Sales](mailto:sales@temporal.io) to discuss your needs.

Your Temporal Cloud consumption combines the costs of Actions and Storage.

**Example**

If you are signed up for Essentials, with &#36;3,000 of monthly spend, your bill will be:

```
Greater of $100 or 5% ⨉ $3,000 = $150, so $150.
```

## Commitment Pricing {#commitment-pricing}

**Commitments with Temporal Credits**

Temporal Cloud offers the option to commit to a minimum spend over a given timeframe.
In exchange for this commitment you receive additional discounts.
Key discount levers include:

- Account Action volume over 200M Actions
- Duration of your commitment (1, 2, or 3 years)

Meet your commitments with any Temporal Cloud spend, including Actions, Storage and your Temporal Cloud Plan.
After making a commitment, Temporal locks in your Actions price based on your expected volume and discounts your Active Storage costs.
This price is used to bill your Actions and Active Storage across your account for the timeframe specified in your commitment.

Commitments must be paid for with Temporal Credits.
Temporal Credits are used to pay your Temporal Cloud consumption, including Temporal Cloud Plan charges.
A Temporal Credit is equivalent to &#36;1 USD.
For example, a credit purchase of &#36;20,000 results in 20,000 Temporal Credits.
A minimum credit purchase equivalent to the first year of your commitment is required.
For multi-year deals please contact [Sales](mailto:sales@temporal.io) for the most accurate pricing.

### Commitment Pricing Q&A

**How do multi-year commitments work?**

Our sales team works with you to match annual credit purchases in line with your expected spend.
This aligns your payments to annual terms rather than one up-front expense.

**What happens if I exhaust my commitment-based Temporal Credits before the end of my term?**

You continue to receive the negotiated discounted prices for the remainder of your term.
You'll be invoiced for another credit purchase based on your most recent calendar month's spend.
This amount is multiplied by the months remaining in the annual portion of your term.
If your previous month spend was &#36;5,000, and you're 10 months through your annual term, you'll be invoiced for 10,000 Temporal Credits to cover the remaining two months.

**What happens if I have unused Temporal Credits at the end of my term?**

Commitments can be difficult to estimate.
Temporal Cloud offers two ways to roll-over unused credits:

- When you renew a commitment for the same or larger amount, Temporal Cloud rolls over any unused credits into your new commitment.
- Should you need to downsize your commitment, Temporal Cloud rolls over up to 10% of your initial credit purchase amount into the new commitment.

**How do I make a commitment and purchase Temporal Credits?**

Contact our team at [sales@temporal.io](mailto:sales@temporal.io) or reach out to your dedicated account manager.
You can also purchase Temporal Cloud commitments credits through [AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-xx2x66m6fp2lo).

### Credit Balance

Your Credit Balance is adjusted each calendar month based on your Credit Usage.

**Example**

An account has purchased credits with an annual spend commitment of &#36;72,000.
In the first calendar month, the account is billed &#36;500 for a Business plan, &#36;5,000 for Actions, &#36;250 for Active Storage and &#36;50 for Retained Storage, a total of &#36;5800.
Their invoice would state:

```
Beginning credit balance of 72,000 - 5800 credits used = 66,200, Temporal Credits remaining.
```

If you have additional questions about credits and volume-based pricing, please contact [sales](mailto:sales@temporal.io) or, if you're already a Temporal Cloud customer, reach out to your dedicated account executive.

## Other pricing {#other-pricing}

Temporal Cloud has additional pricing for other elements of the platform.

### Capacity Modes {#capacity-modes-pricing}

**What are Capacity Modes?** 

Temporal offers On-Demand and Provisioned Capacity modes. 
On-Demand capacity is automatically adjusted based on past usage. 
Provisioned Capacity modes lets you define the capacity that is needed by your Workflow and is useful to handle traffic outside of the standard on-demand limits.
See details on how capacity is set and the associated limits at [Capacity Modes](/cloud/capacity-modes).

:::tip Support, stability, and dependency info

Provisioned Capacity is currently in [pre-release](/evaluate/development-production-features/release-stages#pre-release). 
Please contact your AE or Support to enable this feature.

:::

**How does pricing for Capacity Modes work?**

The number of Actions accrued can be impacted by your capacity mode. 
For On-Demand Capacity Mode, Actions are accrued as usual. 
For Provisioned Capacity there is a minimum number of Actions that must be used per hour for each [Temporal Resource Unit (TRU)](/cloud/capacity-modes) that is provisioned.
If Action volume in an hour does not exceed the minimum allocation, Actions of the subtype `ns_capacity:tru` will be recorded to the required volume. 
The minimum requirement for the first TRU is 0 Actions as it aligns with the default rate limits on Temporal. 
For each additional TRU, there is a minimum hourly requirement of 360,000 Actions Per Hour. 
360,000 Actions per hour represents a 20% utilization of requested resources. 
This can be calculated as 500 APS Per TRU * 3600 Seconds (1 Hour) * 20%= 360,000 Actions. 

For example: 

If you have a namespace that requests 4 TRUs (ie 2,000 APS) for 4 hours and have usage as follows:
* Hour 1: 2,000,000 Actions
* Hour 2: 5,000,000 Actions
* Hour 3: 4,000,000 Actions
* Hour 4: 500,000 Actions
Then the cost of Provisioned Capacity would be calculated as:

4 TRUs Requested - 1 Default TRU included = 3 TRUs with a minimum usage requirement
3 TRUs * 360,000 Actions per Hour= 1,080,000 minimum Actions per Hour
* Hour 1: 2,000,000 Actions > 1,080,000 minimum Actions = No additional Actions accrued
* Hour 2: 5,000,000 Actions > 1,080,000 minimum Actions = No additional Actions accrued
* Hour 3: 4,000,000 Actions > 1,080,000 minimum Actions = No additional Actions accrued
* Hour 4: 500,000 Actions < 1,080,000 minimum Actions so 1,080,000-500,000 Actions = 580,000 additional actions will be added to the hour
Total for 4 hours: 2,000,000+5,000,000+4,000,000+1,080,000=12,080,000 Actions

It TRUs are changed multiple times within an hour, the highest value within that hour will be used to calculate the minimum actions required.

Temporal’s approach to pricing Provisioned Capacity aligns with our goal to only charge for what you use. 
The minimum hourly allocation will have no impact on your price if you utilize the requested capacity above your default by 20% or more, and will only incur an additional charge if the requested capacity is not used. 
To avoid being charged for provisioned capacity it is advised to "return" capacity to the pool and switch back to the On-demand mode when usage is stable. 

### High Availability feature pricing {#high-availability-features}

**How does the pricing for High Availability (HA) features work?**

For workloads with stringent high availability requirements, Temporal Cloud provides same-region, multi-region, and multi-cloud replicas, which add a failover capability.
Enabling HA features for Namespace automatically replicates Workflow Execution data and metadata to a replica in the same region or in a different region.
This allows for a near-seamless failover when incidents or outages occur.

The pricing for High Availability features aligns with the volume of your workloads.
Actions and Storage in your Namespace contribute to your Actions and Storage consumption.
To estimate costs for this deployment model, apply a 2x multiplier to the Actions and Storage in the Namespace you are replicating and include this scaling in your account’s consumption.

:::tip Future Pricing Update

To align with cloud provider network traffic pricing, we are introducing adjustments for multi-region and multi-cloud replication.
Your plan will include a generous base allocation, with additional pay-per-use charges for any network usage beyond that threshold.
Most multi-region and multi-cloud customers will not be impacted by this change.

:::

When upgrading an existing Namespace, some points to consider:

- Temporal won't charge for historical Actions completed prior to upgrading to a Namespace with High Availability features.
  Only ongoing (in-flight) and new Workflow Executions will generate consumption.
- Temporal charges for all Actions of existing (ongoing) and new Workflows from the point of adding a replica.
- Temporal charges for Replicated Storage of retained (historical), running (ongoing), and new Workflow Executions from the point of adding a new replica.

### SCIM and SSO via SAML pricing {#sso-and-saml}

**What costs are associated with SSO/SAML use?**

Single sign-on (SSO) integration using SAML is included for all customers on the Business, Enterprise, and Mission Critical Plans.

**What costs are associated with SCIM?**

To enable SCIM (System for Cross-domain Identity Management), you need an Enterprise or Mission Critical plan or an add-on for the Business plan ($500/month).
Please note that you must configure SSO via SAML to use SCIM.

### Use case cost estimates {#pricing-estimates}

Temporal Cloud uses a consumption-based pricing model based primarily on [Actions](#action) and [Storage](#storage).
Each workload is different.
You can estimate the cost of a specific Workflow by running it at a low volume.
Use the resulting Storage and compute measurements to project your production scale cost.

The examples below provide general estimates based on workload size.
You can also use our calculator on the pricing page to build your estimate.
Our team is always happy to [help you estimate costs](https://pages.temporal.io/contact-us) for your specific workloads and requirements.

| Workload size | Cost (monthly) | Characteristics                            | Actions                                            | Typical use cases                                                                                             |
| ------------- | -------------- | ------------------------------------------ | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Small         | < &#36;50.00   | Modest / transient throughput              | < 1M / month   _(< 0.38 actions per second)_ | General automation  Human dependent processes  Data pipelines  Nightly batch processes      |
| Medium        | < &#36;2K      | Steady or burst throughput                 | < 40M / month  _(< 15 actions per second)_   | Transaction & order systems  Infrastructure automation  Payment Processing  Batch processes |
| Large         | < &#36;15K     | Sustained throughput or multiple use cases | < 400M / month  _(< 150 actions per second)_ | Data processing / sync  Retail order system  KYC & fraud detection                                |
| Web Scale     | &#36;20K+      | "Web scale" and / or numerous use cases    | 1B+ / month  _(400+ actions per second)_     | Social media application  SaaS application service                                                      |

## Billing Questions FAQs {#pricing-faq}

**What payment methods does Temporal accept?**

You can pay with a credit card, ACH, or wire transfer.
To pay for Temporal Cloud with an AWS Account, sign up for [Temporal Cloud Pay-As-You-Go](https://aws.amazon.com/marketplace/pp/prodview-xx2x66m6fp2lo) on the AWS Marketplace.

**How often will I be billed?**

Temporal Cloud issues invoices for the previous month’s usage and costs.
Invoices are issued on the 3rd of the month for the previous month.
For example, invoices for May will be issued at midnight UTC on June 3rd.

**Where can I view my usage and billing information?**

Account Owners and Finance Admins can view their detailed billing data at any time.
Visit the [Usage and Billing dashboards](/cloud/billing-and-cost) in Temporal Cloud.

**How do I purchase Temporal Cloud credits?**

You can purchase Temporal Cloud credits by contacting our team at [sales@temporal.io](mailto:sales@temporal.io).

**What's the minimum cost to run Temporal Cloud?**

The Essentials plan starts at &#36;100/month.
Consumption in excess of your plan's allocations are billed on a consumption basis.

**Can I purchase Temporal Cloud through my Amazon, Azure, or Google Cloud Platform Marketplace?**

There are two ways to purchase Temporal Cloud through AWS Marketplace:

- Pay-As-You-Go available [here](https://aws.amazon.com/marketplace/pp/prodview-xx2x66m6fp2lo)
- Credits: available via private offer, please contact our team at [sales@temporal.io](mailto:sales@temporal.io)

To purchase Temporal Cloud on the Google Cloud Marketplace, please contact our team at [sales@temporal.io](mailto:sales@temporal.io).

**How do I see how many Temporal Cloud credits are remaining?**

To view remaining Temporal Cloud credits, Account Owners and Finance Admins can log in to Temporal Cloud and go to Settings > Billing.
You need appropriate administrative permissions to access this section.

**What happens if I exceed my available credits under a promotion such as the startup program?**

Customers with free credits from the startup program or from a promotion are invoiced once their credit balance is exhausted at the end of that month.

**Do promotional credits expire?**

Credits received through the startup program or an offer have an expiry date.
This date is stated as part of the sign-up process.

**How do I update my payment information?**

Account Owners and Finance Admins can update payment information at any time on the Temporal Cloud [Billing](https://cloud.temporal.io/billing) page under the Plan tab.
You need appropriate administrative permissions to access this section.
Select the "Manage Payment Method" button.

See [this overview](/cloud/billing-and-cost) for more details.

**What happens if my payment fails?**

Temporal will periodically send you email reminders to complete the payment.

**How do I view my invoices and billing history?**

Invoices are emailed to Account Owners or the designated billing contacts.
Account Owners and Finance Admins can view their [detailed billing information](https://cloud.temporal.io/billing) at any time.
See our [billing and cost](/cloud/billing-and-cost) page for details.
You need appropriate administrative permissions to access this section.
Alternatively, to view invoices and billing history, contact Temporal Finance at [ar@temporal.io](mailto: ar@temporal.io).

**Does Temporal charge sales tax/VAT?**

We charge applicable sales tax in US jurisdictions as required.

**How do I cancel my account?**

Account Owners can delete their account and cancel their subscription in the Plans tab in the billing center.
See the [billing and cost](/cloud/billing-and-cost) page for details on how to access the billing center.

**Will I lose access immediately if I cancel my account?**

Customers lose access to Temporal Cloud once Temporal completes the off-boarding process.
Billing is independent of this process.

**Can I reactivate my account after cancellation?**

No.
When your account is canceled, your account data is deleted and cannot be restored.
To return to Temporal Cloud, you must sign up again.
We will assign you a new Temporal account and consider you as a new customer.

---

## Service regions - Temporal Cloud

You can access Temporal Cloud from anywhere with Internet connectivity, no matter where your Temporal Cloud Namespaces are physically located.
Your applications can live in the cloud environment or data center of your choice.
With that in mind, you _will_ reduce latency by creating Namespaces in a region close to where you host your Workers.

This page enumerates the current regions supported by Temporal Cloud Namespaces.

:::tip Service Availability

Visit [status.temporal.io](https://status.temporal.io) to check the status of our supported regions.
On that page, you can also subscribe to updates to receive email notifications whenever Temporal creates, updates or resolves an incident.

:::

### AWS Service Regions

Temporal Cloud operates in the following Amazon Web Services (AWS) regions:

<AWSRegions />

### GCP Service Regions

Temporal Cloud operates the following Google Cloud (GCP) regions:

<GCPRegions />

---

## Service availability - Temporal Cloud

The operating envelope of Temporal Cloud includes throughput, latency, and limits.
Service regions are listed on [this page](/cloud/regions).
If you need more details, [contact us](https://pages.temporal.io/contact-us).

## Throughput expectations {#throughput}

**What kind of throughput can I get with Temporal Cloud?**

Each Namespace in Temporal has a rate limit, which is measured in [Actions](/cloud/pricing#action) per second. 
Temporal offers two different modes for adjusting capacity: On-Demand Capacity or Provisioned Capacity.
With On-Demand Capacity, Namespace capacity is increased automatically along with usage.
With Provisioned Capacity, you can control your capacity limits by requesting Temporal Resource Units (TRUs).

:::tip Support, stability, and dependency info

Provisioned Capacity is currently in [pre-release](/evaluate/development-production-features/release-stages#pre-release). 
Please contact your AE or Support to enable this feature.

:::

## Latency Service Level Objective (SLO) {#latency}

**What kind of latency can I expect from Temporal Cloud?**

Temporal Cloud has a p99 latency SLO of 200ms per region.

The same SLO for normal Worker requests (commands and polling) apply to Nexus in both the caller and handler Namespaces.

### Historical latency data

Latency over a week-long period for starting and signaling Workflow Executions was as follows:

#### January 2026

| Operation                          |  p50   | p90  |  p99 |
| :--------------------------------- | :----: | :--: | ---: |
| `StartWorkflowExecution`           | 14ms | 21ms | 69ms |
| `SignalWorkflowExecution`          | 11ms | 19ms | 46ms |
| `SignalWithStartWorkflowExecution` | 19ms | 37ms | 95ms |

#### March 2024

| Operation                          | p90  |  p99 |
| :--------------------------------- | :--: | ---: |
| `StartWorkflowExecution`           | 24ms | 54ms |
| `SignalWorkflowExecution`          | 14ms | 40ms |
| `SignalWithStartWorkflowExecution` | 24ms | 61ms |

Latency observed from the Temporal Client is influenced by other system components like the Codec Server, egress proxy, and the network itself.
Also, concurrent operations on the same Workflow Execution may result in higher latency.

---

## Service Level Agreement (SLA) - Temporal Cloud

**What is Temporal Cloud's Service Level Agreement? SLA?**

Temporal Cloud provides two availability levels: the [service availability](https://en.wikipedia.org/wiki/Reliability,_availability_and_serviceability) and the contractual [service level agreement](https://en.wikipedia.org/wiki/Service-level_agreement) (SLA).
These levels are set by your deployment mode:

- **Temporal Cloud with standard single-region deployment**:
  Standard Temporal Cloud deployment provides 99.99% availability and a contractual service level agreement (SLA) of 99.9% guarantee against service errors.
- **Temporal Cloud with High Availability feature Namespace deployment**:
  Temporal Cloud Namespaces that use the High Availability feature provide 99.99% availability and contractual service level agreement (SLA) of 99.99% guarantee against service errors.

The same SLA for normal Worker requests (commands and polling) apply to Nexus in both the caller and handler Namespaces.

To calculate the service-error rate, Temporal Cloud captures all requests that arrive in a Namespace during a five-minute interval.
We record the number of gRPC service errors that occurred.
For each Namespace, we calculate the service-error rate as 1 - (count of errors / count of requests).
Rates are averaged per month and reset quarterly.

Errors are recorded against the SLA are service errors, such as the `UNAVAILABLE` [gRPC status code](https://grpc.github.io/grpc/core/md_doc_statuscodes.html).
The following errors are _not_ counted against the SLA:

- `ClientVersionNotSupported`
- `InvalidArgument`
- `NamespaceAlreadyExists`
- `NamespaceInvalidState`
- `NamespaceNotActive`
- `NamespaceNotFound`
- `NotFound`
- `PermissionDenied`
- `QueryFailed`
- `RetryReplication`
- `StickyWorkerUnavailable`
- `TaskAlreadyStarted`
- `Throttling (resources exhausted; triggers retry)`
- `WorkflowExecutionAlreadyStarted`
- `WorkflowNotReady`

Our internal alerting system is based on a [service level objective](https://en.wikipedia.org/wiki/Service-level_objective) (SLO) for all errors, not just errors that count against the SLA.
When we receive an alert that an SLO is not being met, we page our on-call engineers, which often means that issues are resolved before they become noticeable.

Internally, our components are distributed across a minimum of three availability zones per region.
We implement a cell architecture.
Each cell contains the software and services necessary to host a Namespace.
Within each cell, the components are distributed across a minimum of three availability zones per region.

For current system status and information about recent incidents, see [Temporal Status](https://status.temporal.io).

---

## Services, support, and training - Temporal Cloud

Temporal Cloud includes the right level of technical support and guidance, services and training needed to onboard you successfully, assist with design and deployment of your application efficiently and at scale.
Our team has extensive knowledge of Temporal, and a broad set of skills to help you succeed with any project.

Temporal Cloud provides several levels of support, from assisting with for break/fix scenarios to issues and services to helping with onboarding, design/code reviews for your application, and pre-production optimizations and operational readiness.

:::note

The content of this page applies to Temporal Cloud customers only.

:::

## Services offered by Temporal Cloud {#support}

|                             | Essentials                                                                      | Business                                                                                                                                                            | Enterprise                                                                                      | Mission Critical                                                                                                                  |
| --------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| Support Staff               | Trained staff providing break-fix support and general guidance.                 | Trained staff providing break-fix support and general guidance.                                                                                                     | Developer experts who provide advanced support                                                  | Developer experts who provide advanced support                                                                                    |
| Technical Guidance          | Core platform config, platform access, documented features, and basic inquiries | Advanced technical support, Workflow troubleshooting, SDK implementations, and Worker configuration, Quarterly code review or design implementation best practices. | Business+ expert-led code reviews and design implementation best practices, available as needed | Enterprise+ expert guidance on Workflow latency monitoring and optimization; performance recommendations based on real time tests |
| Billing & Cost Optimization | Generic Billing Questions                                                       | Generic Billing Questions                                                                                                                                           | Quarterly review of spend                                                                       | Quarterly review of spend, proactive cost optimization                                                                            |

## Temporal Cloud support guarantees {#guarantees}

Temporal endeavors to ensure you are successful with Temporal Cloud.
We offer explicit guarantees for support.
Temporal Cloud customers get break/fix support with an agreed-upon set of SLAs for prioritized issues.
We use a ticketing system for entering, tracking, and closing these issues.

If an issue occurs, the team also provides support through a dedicated Slack channel, forums, and a knowledge base.
We offer two levels of support defined by their availability and SLAs in the following table:

|                                                  | Essentials                                                                                                     | Business                                                                                                           | Enterprise                                                                                                   | Mission Critical                                                                                             |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
| **Availability**(Based onTime-zones) | **P0–3**: 9–5 Mon–Fri                                                                                          | **P0–3**: 9–5 Mon–Fri                                                                                              | **P0**: 24×7, (On Page Service) **P1–3**: 9–5 Mon–Fri                                            | **P0**: 24×7 (On Page Service) **P1**: 9-5, 7 days/week **P2–3**: Mon–Fri                        |
| **Response Time**                                | **P0**: 1 business day **P1**: 1 business day **P2**: 1 business day **P3**: 2 business days | **P0**: 2 business hours **P1**: 2 business hours **P2**: 1 business day **P3**: 2 business days | **P0**: 30 minutes **P1**: 1 business hour **P2**: 4 business hours **P3**: 1 business day | **P0**: 15 minutes **P1**: 1 business hour **P2**: 4 business hours **P3**: 1 business day |
| **DSE**                                          | -                                                                                                              | -                                                                                                                  | Add-on                                                                                                       | DSE Included (1 Unit)                                                                                        |
| **Channels**                                     | CommunityTemporal Support Portal                                                                          | CommunityTemporal Support Portal                                                                             | CommunityTemporal Support PortalPrivate Slack                                                    | CommunityTemporal Support PortalPrivate Slack                                                    |

:::info Business Hours Timezones

Business Hours will be specified in your contract, including one of three locations: US Pacific time, European Central time, Australia Eastern time

:::

**Priority definitions**

- **P0 - Critical** (Production impacted)
  - The Temporal Cloud service is unavailable or degraded with a significant impact.
- **P1 - High** (Production issue)
  - An issue related to production workloads running on the Temporal Cloud service, or a significant project is blocked.
- **P2 - Normal** (General issues)
  - General Temporal Cloud service or other issues where there is no production impact, or a workaround exists to mitigate the impact.
- **P3 - Low** (General guidance)
  - Questions or an issue with the Temporal Cloud service that is not impacting system availability or functionality.

:::note On Page Service

P0: 24×7 (On Page Service) is offered for Enterprise and Mission Critical accounts.

:::

For pricing details of these support levels, please visit our [pricing page](/cloud/pricing).

## Temporal Dedicated Support Engineer {#dedicated-support-engineer}

Customers on the Mission Critical Plan and (by opting in) Enterprise customers receive access to a Dedicated Support Engineer.
We offer:

- Direct access to a senior developer expert, who becomes part of your Temporal account team, adding deep technical expertise.
  - Our high-touch engagement model goes beyond traditional support to deliver transformative value through hands-on collaboration, proactive optimization, implementation design and operations.
  - Faster issue resolution with direct assistance from someone who already knows your implementation.
  - Focused advisory on best practices and development pairing to ensure high-quality code and scalability.
  - Optimizations through regular checks and recommendations to improve performance and efficiency.
- Priority access to a senior engineer for up to 20 hours per month, providing expert guidance and proactive support for one business unit or major group, specifically within a single region.

Our Services focus on local time zone alignment to ensure optimal responsiveness and efficiency.
Additional service units for this service can be purchased to cover additional groups or regions at &#36;6,000/Mo/Unit.
One unit of Mission Critical Support includes:

- Up to 20 hours per month
- One major group or business unit
- Limited to one region
- Quarterly onsite visits

## Ticketing

Temporal offers a ticketing system for Temporal Cloud customers.
We have an active [community Slack](https://temporalio.slack.com) and an active [community Discourse forum](https://community.temporal.io/) where you can post questions and ask for help.

:::info

The Temporal Support Portal is for Cloud customers only.
Other Temporal users (non-cloud) have full community access excluding the "#support-cloud" channel.
All Cloud customers pay for support as part of their plan.

:::

### Access Temporal Support

1. Go to [support.temporal.io](https://support.temporal.io/).
2. If prompted, log in to Temporal Cloud using the same method you normally use (e.g., Google, Microsoft, email-password, or other methods).
3. You will be presented with a screen where you can view open and closed tickets for your Temporal account, as well as submit a new ticket.

To request assistance from Temporal Support, see [Create a ticket](#support-ticket).

### Create a Ticket {#support-ticket}

:::info

This procedure applies only to Temporal Cloud customers whose contracts include paid support.
If you need assistance and don't have paid support, post your request in the [Temporal Community Forum](https://community.temporal.io) or the `#support-cloud` channel of the [Temporal workspace](https://t.mp/slack) in Slack.

:::

To create a ticket in the Temporal Support Portal:

1. Go to [support.temporal.io](https://support.temporal.io/).
2. If prompted, log in to Temporal Cloud using the same method you normally use (e.g., Google, Microsoft, email-password, or other methods).
3. Click the **Create Ticket** button in the top right corner.
4. On the **Submit a ticket** page, enter the details of your request into the form. **Name**, **Subject**, and **Description** are required.
5. At the bottom of the form, choose **Submit**.

## Developer resources {#developer-resources}

Temporal offers developer resources and a variety of hands-on tutorials to get you started and learn more advanced Temporal concepts.

- [Get started with Temporal](https://learn.temporal.io/getting_started): Start your journey with Temporal with this guide that helps you set up your development environment, run an existing Temporal app, and then build your first app from scratch using our SDKs.
- [Courses](https://learn.temporal.io/courses): Learn and apply Temporal concepts in our free, self-paced, hands-on courses.
- [Tutorials](https://learn.temporal.io/tutorials): Apply Temporal concepts to build real-world applications with these hands-on tutorials.
- [Example applications](https://learn.temporal.io/examples): Explore example applications that use Temporal and gain a clearer understanding of how Temporal concepts work in a complex application.

---

## Understanding Temporal

Temporal offers an entirely new way to build scalable and reliable applications.

## Build Invincible Apps

In any complex system, failures are bound to happen.
Software engineers spend a lot of time ensuring that what they build can withstand potential failures.
Temporal makes your code execution reliable and durable by default.

Normally, if a crash occurs then the state of your application's execution is lost.
The application has no memory of what happened before the failure, requiring extensive error handling logic and complex recovery code to resume.
The process is time-consuming and error-prone, making it difficult to ensure reliability.

Temporal tracks the progress of your application.
If something goes wrong, like a power outage, it guarantees that your application can pick up right where it left off — it’s like having the ultimate autosave.
Offloading the responsibility of failure management from the application to the platform removes the need for extensive recovery coding, testing, and maintenance tasks.

### Durable Execution

Temporal is a Durable Execution Platform.
Durable Execution ensures that your application behaves correctly despite adverse conditions by guaranteeing that it will run to completion.
This shift simplifies the development process. If a failure or a crash happens, your business processes keep running seamlessly without interruptions.
Developers shift their focus on business logic rather than infrastructure concerns and create applications that are inherently scalable and maintainable.

Thousands of developers trust Temporal for use cases like order processing, customer onboarding, and payment handling because it enables them to build invincible applications that are resilient, durable, and _just work_.
With Temporal, your applications keep running, no matter what happens.

## Temporal Application: The Building Blocks

### Workflow

Conceptually, a Workflow is a sequence of steps.
You've likely encountered Workflows in your daily life, whether it's:

- Using a mobile app to transfer money
- Booking a vacation
- Filing an expense report
- Creating a new employee onboarding process
- Deploying cloud infrastructure
- Training an AI model

A Temporal Workflow is your business logic, defined in code, outlining each step in your process.

Temporal isn’t a no-code Workflow engine — it is **Workflows-as-Code**.
Instead of dragging and dropping steps in a visual interface, you write your Workflows in code in your favorite programming language, code editor, and other tools.
No-code engines eventually hit their limitations however, Temporal gives you full control and flexibility over your business processes.
This allows you to build exactly what you need.

### Activities

Activities are the individual units of work in your Workflow.
Activities are defined as either functions or methods, depending on the programming language.
Activities often involve interacting with the outside world, such as sending emails, making network requests, writing to a database, or calling an API, which are prone to failure.
You can call Activities directly from your Workflow code.

If an Activity fails, Temporal automatically retries it based on your configuration.
Since Activities often rely on external systems, transient issues can occur.
These include temporary but critical problems like network failures, timeouts, or service outages.
You have full control over how often and how many times these retries should happen for each Activity.

### SDK

Developers create Temporal applications by writing code, just like you would to create any other software.

A Temporal SDK (software development kit) is an open-source library that developers add to their application to use Temporal.
It provides everything needed to build Workflows, Activities, and various other Temporal features in a specific programming language.

Temporal offers seven SDKs: .NET, Go, Java, PHP, Python, Ruby, TypeScript.
Since Temporal supports multiple programming languages, you can mix-and-match between languages for polyglot teams.
You can easily add any Temporal SDK to your current projects without changing the tools you're already using to build and deploy.
Temporal fits right into your existing tech stack.

## Temporal Service

Temporal has two main parts:

1. Your application
2. The Temporal Service (a set of services and components)

At the heart of Temporal architecture is the Temporal Service, which provides durability, scalability, and reliability for your application.
Your application communicates with the Temporal Service and the Temporal Service oversees the execution of critical tasks such as making an API call, then records their completion.
It maintains a detailed history of each event, which it reliably persists to a database.

One of the biggest advantages of the Temporal Service is how it handles failures.
The Temporal Service maintains a meticulous record of every step in your Workflows.
By keeping a history of every step in your Workflow, it ensures that even if something goes wrong your Workflow can continue from the last successful point.
The Temporal Service knows exactly where to resume without losing any work.
This saves you from having to write complex error handling code or painstaking recovery mechanisms yourself.

You can run the Temporal Service on your own infrastructure or use Temporal Cloud, a managed service that handles operational overhead and offers scalability and expert support.

## Workers

The real strength of Temporal comes from the combination of your application and the Temporal Service.
Whenever your application needs to perform a task, like sending a notification or processing a payment, the Temporal Service orchestrates what needs to be done.
Workers, which are part of your application and provided by the Temporal SDK, then carry out the tasks defined in your Workflow.

The Worker polls the Temporal Service to see if there are tasks available and the Temporal Service matches the task with the Worker.
The Worker runs the Workflow code based on the details specified in the task.

This collaboration is crucial for building reliable, scalable, and durable applications.
You can run multiple Workers — often dozens, hundreds, or even thousands — to improve application performance and scalability.

A common misconception is that the Temporal Service runs your code.
In fact, the Worker runs your code and works with your data directly.
Temporal applications are secure by design.
Workflows and Activities are seamlessly deployed within your infrastructure, fully integrated into your application.
Your data is also protected with your encryption libraries and keys.
You maintain full control over the security of your application from end to end.

## Visibility

There are two tools provided by Temporal that allow you to see behind the scenes and interact with your Workflows.
These are powerful for debugging uses and provide real-time monitoring of your applications.

### Temporal UI

The Temporal UI is a browser-based user interface that allows you to see the progress of your application.
Also, known as the Web UI, it can also help you to quickly isolate, debug, and resolve production problems.

<CaptionedImage src="/img/webui/workflow-details-page-hiw.avif" title="Recent Workflows page" />

### Temporal CLI

The Temporal CLI is a command-line interface tool for managing, monitoring, and debugging Temporal Applications.
Through your terminal, you can:

- Start a Workflow
- Trace the progress of a Workflow
- Cancel or terminate a Workflow
- And perform other operations

The Temporal CLI provides developers with direct access to a Temporal Service for local development purposes.

### Event History

With Temporal, your Workflows can seamlessly recover from crashes. This is made possible by the [Event History](https://docs.temporal.io/workflow-execution/event), a complete and durable log of everything that has happened in the lifecycle of a Workflow Execution, as well as the ability of the Temporal Service to durably persist the Events during Replay.

Temporal uses the Event History to record every step taken along the way. Each time your Workflow Definition makes an API call to execute an Activity or start a Timer for instance, it doesn’t perform the action directly. Instead, it sends a Command to the Temporal Service.

A Command is a requested action issued by a Worker to the Temporal Service after a Workflow Task Execution completes. The Temporal Service will act on these Commands such as scheduling an Activity or scheduling a timer. These Commands are then mapped to Events which are persisted in case of failure. For example, if the Worker crashes, the Worker uses the Event History to replay the code and recreate the state of the Workflow Execution to what it was immediately before the crash. It then resumes progress from the point of failure as if the failure never occurred.

For a deep dive into the Event History or Commands, visit the Temporal [Encyclopedia page](/encyclopedia/event-history) or enroll in one of [our courses](https://learn.temporal.io/courses/).

## Reliable as Gravity

Temporal provides effortless durability, allowing applications to run for days, weeks, or even years without interruption even if the underlying infrastructure fails.
This is what we call _Durable Execution_. Temporal also represents a paradigm shift in software development.
It's not just about making existing patterns more reliable; it's about enabling entirely new approaches to building complex, distributed systems.

Temporal simplifies state management and developers don't have to write tons of extra code to handle every possible thing that could go wrong.
With built-in scalability, Temporal ensures that your application runs smoothly, no matter its size or complexity.

:::tip

Follow one of our tutorials to [Get Started](https://learn.temporal.io/getting_started/) learning how to use a Temporal SDK.
Or, jump straight into an [Introduction to Temporal 101](https://learn.temporal.io/courses/temporal_101/) course.

Looking for more? Explore Temporal's [Resource Library](https://temporal.io/resources).
:::

---

## Temporal Use Cases and Design Patterns

This page provides an overview of how leading organizations leverage Temporal to solve real-world problems, general use cases, and architectural design patterns.

## Use Cases of Temporal in Production

Here are some examples where Temporal is most impactful and running in production at large organizations today. For more examples, see our [Temporal Use Cases](https://temporal.io/in-use) page.

### Transactions

Actions or activities involving two or more parties or things that reciprocally affect or influence each other. For example:

- [Payment processing at Stripe](https://temporal.io/resources/on-demand/stripe)
- [Money movement at Coinbase](https://temporal.io/in-use/coinbase)
- [Content management at Box](https://temporal.io/resources/case-studies/box)

### Business processes

A sequence of tasks that find their end in the delivery of a service or product to a client. For example:

- [Bookings at Turo](https://temporal.io/replay/videos/temporal-adoption-and-integration-at-turo)
- [Orders/logistics at Maersk](https://temporal.io/replay/videos/building-a-time-machine-for-the-logistics-industry)
- [Marketing Campaigns at AirBnb](https://medium.com/airbnb-engineering/journey-platform-a-low-code-tool-for-creating-interactive-user-workflows-9954f51fa3f8)
- [Human-in-the-loop at Checkr](https://temporal.io/in-use/checkr)

### Entity lifecycle

Complex long-running processes that accumulate state over time. For example:

- [Mortgage underwriting applications at ANZ](https://temporal.io/in-use/anz-story)
- [Menu versioning at Yum! Brands](https://temporal.io/replay-2023/videos/synchronizing-concurrent-workflows)

### Operations

An automated method for getting a repeatable, mundane task accomplished. For example:

- [Infrastructure services at DataDog](https://www.youtube.com/watch?v=Hz7ZZzafBoE)
- [Custom CI/CD at Netflix](https://temporal.io/replay-2023/videos/actor-workflows-reliably-orchestrating-thousands-of-flink-clusters-at)

### AI / ML and Data Engineering

AI and ML developers face challenges in system orchestration, such as managing complex data pipelines and job coordination across GPU resources.
Temporal's code-first approach helps build reliable services faster, making it popular among AI companies. For example:

- [Orchestrating video processing at Descript](https://temporal.io/blog/ai-ml-and-data-engineering-workflows-with-temporal#descript)
- [Automating data pipelines at Neosync](https://temporal.io/blog/ai-ml-and-data-engineering-workflows-with-temporal#neosync)

### AI Agents

AI Agents present new uses for Temporal, such as maintaining state over long periods and enabling seamless human intervention when needed.
Temporal ensures Durable Execution of tools, LLMs, and conversations, letting you focus on business logic instead of handling failures. For example:

- [Creating reliable, observable Agents at Lindy](https://temporal.io/resources/case-studies/lindy-reliability-observability-ai-agents-temporal-cloud)
- [Long-running, durable Agents at Dust](https://temporal.io/blog/how-dust-builds-agentic-ai-temporal)
- [Creating account summaries with Agents at ZoomInfo](https://temporal.io/resources/on-demand/account-summaries-gen-ai)

## General Use Cases

### Human in the Loop

"Human in the Loop" systems require human interaction for certain steps, such as customer onboarding, forms, or invoice approval.
These are event driven system with humans generating events, and may be challenging to implement due to timing or unreliable connections between the human to the rest of the system.
They can use schedules and timers to prompt for user input.

**Example**: [Background checks example using the Go SDK](https://learn.temporal.io/examples/go/background-checks/).

**Code Sample**: [Candidate acceptance example prompting for a response](https://learn.temporal.io/examples/go/background-checks/candidate-acceptance)

### Polyglot Systems

Modern development teams often work with different programming languages based on their expertise and project requirements. Temporal supports this through built-in multi-language capabilities, allowing teams to continue using their preferred languages while working together.

The example below showcases how Workflow Executions, written in different languages, can send messages to each other. Go, Java, PHP, and TypeScript SDKs are represented in this sample. It also shows how to properly propagate errors, including how to do so across Workflows written in different languages.

**Example**: [Polyglot example](https://github.com/temporalio/temporal-polyglot).

### Long Running Tasks

This use case is particularly relevant for scenarios like shopping cart Workflows in an eCommerce app, where you can handling long-running tasks efficiently without managing state in a separate database.
It processes one message at a time, ensuring each message is processed only once.

This approach addresses issues that can arise with long message processing times, which in other systems might cause consumer failover (typically with a default 5-minute message poll timeout) and potentially result in duplicate message processing by multiple consumers.
Temporal's ability to handle extended task durations makes it well-suited for such scenarios.
The [heartbeat](/encyclopedia/detecting-activity-failures#activity-heartbeat) feature allows you to know that an activity is still working, providing insight into the progress of long-running processes.

**Example**: [eCommerce example](https://learn.temporal.io/tutorials/go/build-an-ecommerce-app/).

**Code Sample**: [Temporal eCommerce](https://github.com/temporalio/temporal-ecommerce)

## Design Patterns

### Saga

The Saga pattern is a design pattern used to manage and handle failures in complex Workflows by breaking down a transaction into a series of smaller, manageable sub-transactions.
If a step in the Workflow fails, the Saga pattern compensates for this failure by executing specific actions to undo the previous steps.
This ensures that even in the event of a failure, the system can revert to a consistent state.

**Examples:**

- [Build a trip booking application in Python](https://learn.temporal.io/tutorials/python/trip-booking-app/).
- [Saga Pattern with Temporal Whitepaper](https://pages.temporal.io/download-saga-pattern-made-easy)
- [To choreograph or orchestrate your saga, that is the question](https://temporal.io/blog/to-choreograph-or-orchestrate-your-saga-that-is-the-question)
- [Saga Webinar](https://pages.temporal.io/on-demand-webinar-what-is-a-saga.html)

### State Machine

A state machine is a software design pattern used to modify a system’s behavior in response to changes in its state.
While state machines are widely used in software development, applying them to complex business processes can be a difficult undertaking.
Temporal simplifies the complexity of state machines by providing a structured approach to workflow development, avoiding the intricate state management code required for state machines.

**Example**: [State Machine Simplified Whitepaper](https://pages.temporal.io/download-state-machines-simplified.html)

:::tip

If you're interested in code to help get you started, check out our [Temporal Example Applications](https://learn.temporal.io/examples/), [Getting Starting Tutorials](https://learn.temporal.io/getting_started/), or [Project-based Tutorials](https://learn.temporal.io/tutorials/).

:::

---

## Why Temporal?


Temporal solves many problems that developers face while building distributed applications.
But most of them revolve around these three themes:

- Reliable distributed applications
- Productive development paradigms and code structure
- Visible distributed application state

:::tip See Temporal in action
Watch the following video to see how Temporal ensures an order-fulfillment system can recover from various failures, from process crashes to unreachable APIs.

    <iframe width="560" height="315"
        src="https://www.youtube.com/embed/dNVmRfWsNkM?si=cfwAJgr2zaoro97P"
        title="YouTube video player"
        frameBorder="0"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
        referrerPolicy="strict-origin-when-cross-origin" allowFullScreen></iframe>

:::

## Reliable execution

**How does Temporal make applications reliable?**

Temporal makes it easier for developers to build and operate reliable, scalable applications without sacrificing productivity.
The design of the system ensures that, once started, an application's main function executes to completion, whether that takes minutes, hours, days, weeks, or even years.
Temporal calls this _Durable Execution._

## Code structure

**How does Temporal simplify application code for software developers?**

By shifting the burden of failure handling from the application to the platform, there is less code for application developers to write, test, and maintain.
Temporal's programming model offers developers a way to express their business logic into coherent _Workflows_ that are much easier to develop than distributed code bases.

Choose the SDK that best suits your preferred programming language and start writing your business logic.
Integrate your favorite IDE, libraries, and tools into your development process.
Temporal also supports polyglot and idiomatic programming - which enables developers to leverage the strengths of various programming languages and integrate Temporal into existing codebases.
Developers achieve all of this without having to manage queues or complex state machines.

## State visibility

**How does Temporal make it easier to view the state of the application?**

Temporal provides out-of-the-box tooling that enables developers to see the state of their applications whenever they need to.
The Temporal CLI allows developers to manage, monitor, and debug Temporal applications effectively.
The browser-based Web UI lets you quickly isolate, debug, and resolve production problems.

---

## Getting started with Temporal

Temporal offers a range of SDKs to help you build Temporal applications.
The SDKs are available for .NET, Go, Java, PHP, Python, Ruby, TypeScript.

## Temporal Go SDK

Get started with the [Temporal Go SDK](https://learn.temporal.io/getting_started/go).

[](https://learn.temporal.io/getting_started/go)

## Temporal Java SDK

Get started with the [Temporal Java SDK](https://learn.temporal.io/getting_started/java).

[](https://learn.temporal.io/getting_started/java)

## Temporal PHP SDK

Get started with the [Temporal PHP SDK](https://learn.temporal.io/getting_started/php).

[](https://learn.temporal.io/getting_started/php)

## Temporal Python SDK

Get started with the [Temporal Python SDK](https://learn.temporal.io/getting_started/python).

[](https://learn.temporal.io/getting_started/python)

## Temporal TypeScript SDK

Get started with the [Temporal TypeScript SDK](https://learn.temporal.io/getting_started/typescript).

[](https://learn.temporal.io/getting_started/typescript)

---

## Temporal Docs

<HomePageHero />

---

## Codec Server - Temporal Platform feature guide

Temporal Server stores and persists the data handled in your Workflow Execution.
Encrypting this data ensures that any sensitive application data is secure when handled by the Temporal Server.

For example, if you have sensitive information passed in the following objects that are persisted in the Workflow Execution Event History, use encryption to secure it:

- Inputs and outputs/results in your [Workflow](/workflow-execution), [Activity](/activity-execution), and [Child Workflow](/child-workflows)
- [Signal](/sending-messages#sending-signals) inputs
- [Memo](/workflow-execution#memo)
- Headers (verify if applicable to your SDK)
- [Query](/sending-messages#sending-queries) inputs and results
- Results of [Local Activities](/local-activity) and [Side Effects](/workflow-execution/event#side-effect)
- [Application errors and failures](/references/failures).
  Failure messages and call stacks are not encoded as codec-capable Payloads by default; you must explicitly enable encoding these common attributes on failures.
  For more details, see [Failure Converter](/failure-converter).

Using encryption ensures that your sensitive data exists unencrypted only on the Client and the Worker Process that is executing the Workflows and Activities, on hosts that you control.

By default, your data is serialized to a [Payload](/dataconversion#payload) by a [Data Converter](/dataconversion).
To encrypt your Payload, configure your custom encryption logic with a [Payload Codec](/payload-codec) and set it with a [custom Data Converter](/default-custom-data-converters#custom-data-converter).

A Payload Codec does byte-to-byte conversion to transform your Payload (for example, by implementing compression and/or encryption and decryption) and is an optional step that happens between the Client and the [Payload Converter](/payload-converter):

<CaptionedImage
    src="/diagrams/remote-data-encoding.svg"
    title="Remote data encoding architecture" />

You can run your Payload Codec with a [Codec Server](/codec-server) and use the Codec Server endpoints in the Web UI and CLI to decode your encrypted Payload locally.
For details on how to set up a Codec Server, see [Codec Server setup](#codec-server-setup).

However, if you plan to set up [remote data encoding](/remote-data-encoding) for your data, ensure that you consider all security implications of running encryption remotely before implementing it.

When implementing a custom codec, it is recommended to perform your compression or encryption on the entire input Payload and store the result in the data field of a new Payload with a different encoding metadata field.
This ensures that the input Payload's metadata is preserved.
When the encoded Payload is sent to be decoded, you can verify the metadata field before applying the decryption.
If your Payload is not encoded, it is recommended to pass the unencoded data to the decode function instead of failing the conversion.

Examples for implementing encryption:

- [Go sample](https://github.com/temporalio/samples-go/tree/main/encryption)
- [Java sample](https://github.com/temporalio/samples-java/tree/main/core/src/main/java/io/temporal/samples/encryptedpayloads)
- [Python sample](https://github.com/temporalio/samples-python/tree/main/encryption)
- [TypeScript sample](https://github.com/temporalio/samples-typescript/tree/main/encryption)
- [.NET sample](https://github.com/temporalio/samples-dotnet/tree/main/src/Encryption)

## Codec Server setup {#codec-server-setup}

Use a Codec Server to programmatically decode your encoded [payloads](/dataconversion#payload).

A Codec Server is an HTTP server that uses your custom Codec logic to decode your data remotely.
The Codec Server is independent of the Temporal Service and decodes your encrypted payloads through predefined endpoints. You create, operate, and manage access to your Codec Server in your own environment.
The Temporal CLI and the Web UI in turn provide built-in hooks to call the Codec Server to decode encrypted payloads on demand.

The Codec Server is independent of the Temporal Server and decodes your encrypted payloads through endpoints.
When you configure a Codec Server endpoint in the Temporal Web UI or CLI, the Web UI and CLI use the remote endpoint to receive decoded payloads from the Codec Server.
See [API contract requirements](#api-contract-specifications).

Decoded payloads can then be displayed in the Workflow Execution Event History on the Web UI. Note that when you use a Codec Server, the decoded payloads are decoded and returned on the client side only; payloads on the Temporal Server (whether on Temporal Cloud or a self-hosted Temporal Service) remain encrypted.

Because you create, operate, and manage access to your Codec Server in your controlled environment, ensure that you consider the following:

- When you register a Codec Server endpoint with your Web UI, expect the Codec Server to receive multiple requests per Workflow Execution.
- Ensure that you secure access to your Codec Server. For details, see [Authorization](#authorization). You might need some form of [Key management infrastructure](/key-management) for sharing your encryption keys between the Workers and your Codec Server.
- You will need to enable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) on the HTTP/HTTPS endpoints in your Codec Server to receive requests from the Temporal Web UI.
- You may introduce latency in the Web UI when sending and receiving payloads to the Codec Server.

Your Codec Server should share logic with the custom [Payload Codec](/payload-codec) used elsewhere in your application.

### API contract specifications

When you create your Codec Server to handle requests from the Web UI, the following requirements must be met.

#### Endpoints

The Web UI and CLI send a POST to a `/decode` endpoint. In your Codec Server, create a `/decode` path and pass the incoming payload to the decode method in your Payload Codec.

For examples on how to create your Codec Server, see the following Codec Server implementation samples:

- [Go](https://github.com/temporalio/samples-go/tree/main/codec-server)
- [Java](https://github.com/temporalio/sdk-java/tree/master/temporal-remote-data-encoder)
- [Python](https://github.com/temporalio/samples-python/blob/main/encryption/codec_server.py)
- [TypeScript](https://github.com/temporalio/samples-typescript/blob/main/encryption/src/codec-server.ts)
- [.NET](https://github.com/temporalio/samples-dotnet/blob/main/src/Encryption/CodecServer/Program.cs)

You can also add a [verification step](#authorization) to check whether the incoming request has the required authorization to access the decode logic in your Payload Codec.

#### Headers

Each request from the Web UI to your Codec Server includes the following headers:

- `Content-Type: application/json`: Ensure that your Codec Server can accommodate this [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types).

- `X-Namespace: {namespace}`: This is a custom HTTP Header. Ensure that the [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) configuration in your Codec Server includes this header.

- [Optional] `Authorization: <credentials>`: Include this in your CORS configuration when enabling authorization with your Codec Server.

For details on setting up authorization, see [Authorization](#authorization).

#### Request body

The general specification for the `POST` request body contains payloads.
By default, all field values in your payload are base64 encoded, regardless of whether they are encrypted by your custom codec implementation.

The following example shows a sample `POST` request body with base64 encoding.

```json
{
  "payloads": [{
    "metadata": {
      "encoding": <base64EncodedEncodingHint>
    },
    "data": <encryptedPayloadData>
  }, ...]
}
```

#### CORS

By default, in cross-origin Fetch/XHR invocations, browsers will not send credentials.
Enable [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) requests on your Codec Server to receive HTTP/HTTPS requests from the Temporal Web UI.

At a minimum, enable the following responses from your Codec Server to allow requests coming from the Temporal Web UI:

- `Access-Control-Allow-Origin`
- `Access-Control-Allow-Methods`
- `Access-Control-Allow-Headers`

For example, for Temporal Cloud Web UI hosted at https://cloud.temporal.io, enable the following in your Codec Server:

- `Access-Control-Allow-Origin: https://cloud.temporal.io`
- `Access-Control-Allow-Methods: POST, GET, OPTIONS`
- `Access-Control-Allow-Headers: X-Namespace, Content-Type`

For details on what a sample request/response looks like from the Temporal Web UI, see [Sample Request/Response](#sample-requestresponse).
If setting authorization, include `Authorization` in your `Access-Control-Allow-Headers`.
For details on setting up authorization, see [Authorization](#authorization).

#### Authorization

It is important to establish how you will provide access to your Codec Server.
Because it is designed to decode potentially sensitive data with a single API call, access to a production Codec Server should be restricted.

Depending on your infrastructure and risk levels, it might be sufficient to restrict HTTP ingress to your Codec Server (such as by using a VPN like [WireGuard](https://www.wireguard.com/)).
The Temporal Web UI can communicate with a Codec Server that is only accessible on `localhost`, so this is a legitimate security pattern.
However, if your Codec Server is exposed to the internet at all, you will likely need an authentication solution.

If you are already using an organization-wide authentication provider, you should integrate it with your Codec Server. Remember, a Codec Server is just a standalone HTTP server, so you can use existing libraries for OAuth, [Auth0](https://auth0.com/), or any other protocol.
[This repository](https://github.com/pvsone/codec-cors-credentials) contains an example of using Auth0 to handle browser-based auth to a Codec Server.

To enable authorization from the Web UI (for both a self-hosted Temporal Service and Temporal Cloud), your Codec Server must be an HTTPS Server.

**Temporal Cloud**

The Temporal Cloud UI provides an option to pass access tokens (JWT) to your Codec Server endpoints.
Use the access tokens to validate access and then return decoded payloads from the Codec Server.

You can enable this by selecting **Pass access token** in your Codec Server endpoint interface where you add your endpoint.
Enabling this option in the Temporal Cloud UI adds an authorization header to each request sent to the Codec Server endpoint that you set.

In your Codec Server implementation, verify the signature on this access token (in your authorization header) against [our JWKS endpoint](https://login.tmprl.cloud/.well-known/jwks.json).

{/* Commenting this for now. _/}
{/_ If you want to unpack the claims in your token to add additional checks on whether the user has valid access to the Namespace and payloads they are trying to access, you can implement it using Auth0 SDKs, middleware, or one of the third-party libraries at JWT.io. */}

The token provided from Temporal Cloud UI contains the email identifier of the person requesting access to the payloads.
Based on the permissions you have provided to the user in your access control systems, set conditions in your Codec Server whether to return decoded payloads or just return the original encoded payloads.

**Self-hosted Temporal Service**

On a self-hosted Temporal Service, configure [authorization in the Web UI configuration](/references/web-ui-configuration#auth) in your Temporal Service setup.

With this enabled, you can pass access tokens to your Codec Server and validate the requests from the Web UI to the Codec Server endpoints that you set.
Note that with a self-hosted Temporal Service, you must explicitly configure authorization specifications for the Web UI and CLI.

#### Sample request/response

Consider the following sample request/response when creating and hosting a Codec Server with the following specifications:

- Scheme: `https`
- Host: `dev.mydomain.com/codec`
- Path: `/decode`

```json
HTTP/1.1 POST /decode
Host: https://dev.mydomain.com/codec
Content-Type: application/json
X-Namespace: myapp-dev.acctid123
Authorization: Bearer <token>

{"payloads":[{"metadata":{"encoding":"anNvbi9wcm90b2J1Zg==","messageType":"dGVtcG9yYWxfc2hvcC5vcmNoZXN0cmF0aW9ucy52MS5TdGFydFNob3BwaW5nQ2FydFJlcXVlc3Q="},"data":"eyJjYXJ0SWQiOiJleGFtcGxlLWNhcnQiLCJzaG9wcGVySWQiOiJ5b3VyLXNob3BwZXItaWQtZXhhbXBsZSIsImVtYWlsIjoieW91ci1lbWFpbEBkb21haW4uY29tIn0"}]}

200 OK
Content-Type: application/json

{
  "payloads": [{
    "metadata":{
      "encoding": "json/protobuf",
      "messageType": "temporal_shop.orchestrations.v1.StartShoppingCartRequest"
    },
    "data":{
      "cartId":"example-cart",
      "shopperId":"your-shopper-id-example",
      "email":"your-email@domain.com"
    }}]
}
```

You can also perform remote encoding on an `/encode` endpoint, which looks the same in reverse:

- Scheme: `https`
- Host: `dev.mydomain.com/codec`
- Path: `/encode`

```json
HTTP/1.1 POST /encode
Host: https://dev.mydomain.com/codec
Content-Type: application/json
X-Namespace: myapp-dev.acctid123
Authorization: Bearer <token>

{"payloads":[{"metadata":{"encoding":"json/protobuf","messageType":"temporal_shop.orchestrations.v1.StartShoppingCartRequest"},"data":{"cartId":"example-cart","shopperId":"your-shopper-id-example","email":"your-email@domain.com"}}]}

200 OK
Content-Type: application/json

{
  "payloads": [
    {
      "metadata": {
        "encoding": "anNvbi9wcm90b2J1Zg==",
        "messageType": "dGVtcG9yYWxfc2hvcC5vcmNoZXN0cmF0aW9ucy52MS5TdGFydFNob3BwaW5nQ2FydFJlcXVlc3Q="
      },
      "data": "eyJjYXJ0SWQiOiJleGFtcGxlLWNhcnQiLCJzaG9wcGVySWQiOiJ5b3VyLXNob3BwZXItaWQtZXhhbXBsZSIsImVtYWlsIjoieW91ci1lbWFpbEBkb21haW4uY29tIn0"
    }
  ]
}
```

### Set your Codec Server endpoints with Web UI and CLI

After you create your Codec Server and expose the requisite endpoints, set the endpoints in your Web UI and CLI.

#### Web UI

On Temporal Cloud and self-hosted Temporal Service, you can configure a Codec Server endpoint to be used for a Namespace in the Web UI.

<CaptionedImage
    src="/img/info/set-codec-endpoint-form.png"
    title="Codec Server endpoint Namespace setting"
/>

To set a Codec Server endpoint on a Namespace, do the following.

1. In the Web UI, go to Namespaces, select the Namespace where you want to configure the Codec Server endpoint, and click **Edit**.
1. In the **Codec Server** section on the Namespace configuration page, enter your Codec Server endpoint and port number.
1. Optional: If your Codec Server is configured to [authenticate requests](#authorization) from Temporal Web UI, enable **Pass access token** to send a JWT access token with the HTTPS requests.
1. Optional: If your Codec Server is configured to [verify origins of requests](#cors), enable **Include cross-origin credentials**.

On Temporal Cloud, you must have [Namespace Admin privileges](/cloud/users#namespace-level-permissions) to add a Codec Server endpoint on the Namespace. Setting a Codec Server endpoint on a Cloud Namespace enables it for all users on the Namespace.

Setting a Codec Server endpoint on a self-hosted Temporal Service enables it for the entire Temporal Service. You can use a single Codec Server to handle different encoding and decoding routes for each namespace.

You can also override the global Codec Server setting at the browser level. This can be useful when developing, testing, or troubleshooting encoding functionality.

<CaptionedImage
    src="/img/info/data-encoder-button.png"
    title="Codec Server endpoint browser setting"
/>

To set a browser override for the Namespace-level endpoint, do the following.

1. Navigate to **Workflows** in your Namespace.
2. In the top-right corner, select **Configure Codec Server**.
3. Select whether you want to use the Namespace-level (or Temporal Service-level for self-hosted Temporal Service) or the browser-level Codec Endpoint setting as the default for your browser.
   In Temporal Cloud:
   - **Use Namespace-level settings, where available. Otherwise, use my browser setting.**
     Uses the Namespace-level Codec Server endpoint by default.
     If no endpoint is set on the Namespace, your browser setting is applied.
   - **Use my browser setting and ignore Namespace-level setting.**
     Applies your browser-level setting by default, overriding the Namespace-level Codec Server endpoint.
4. Enter your Codec Server endpoint and port number.
5. Optional: If your Codec Server is configured to [authenticate requests](#authorization) from Temporal Web UI, enable **Pass access token** to send a JWT access token with the HTTPS requests.
6. Optional: If your Codec Server is configured to [verify origins of requests](#cors), enable **Include cross-origin credentials**.

In a self-hosted Temporal Service with dedicated UI Server configuration, you can also set the codec endpoint in the UI server [configuration file](/references/web-ui-configuration#codec):

```yaml
codec:
    endpoint: {{ default .Env.TEMPORAL_CODEC_ENDPOINT "{namespace}"}}
```

#### CLI

You can configure a Codec Server endpoint with the Temporal CLI using the `--codec-endpoint` flag.

For example, if you are running your Codec Server on `http://localhost:8888`, you can use `env set` to set the endpoint globally:

```bash
temporal env set --codec-endpoint "http://localhost:8888"
```

If your Codec Server endpoint is not set globally, provide the `--codec-endpoint` option with each command.
For example, to see the decoded output of the Workflow Execution "yourWorkflow" in the Namespace "yourNamespace", run:

```bash
temporal --codec-endpoint "http://localhost:8888" --namespace "yourNamespace" workflow show --workflow-id "yourWorkflow"  --run-id "<yourRunId>" --output "table"
```

For details, see the [CLI reference](/cli/).

If your Codec Server requires authentication, the Temporal CLI will also accept a `--codec-auth` parameter to supply an
authorization header:

```shell
temporal workflow show \
   --workflow-id converters_workflowID \
   --codec-endpoint 'http://localhost:8081/{namespace}' \
   --codec-auth 'auth-header'
```

### Working with Large Payloads

Codec Servers can be used for more than encryption and decryption of sensitive data.
Codec Server behavior is left up to implementers -- they can also call external services or perform other tasks, as long as they hook in at the encoding and decoding stages of a Workflow payload.

By default, Temporal limits payload size to 4MB.
If this limitation is problematic for your use case, you could implement a codec that persists your payloads to an object store outside of workflow histories.
An example implementation is available from [DataDog](https://github.com/DataDog/temporal-large-payload-codec).

### Temporal Nexus

The Data Converter works the same for a Nexus Operation as it does for other payloads sent between a Worker and Temporal Cloud.
Both the caller and handler Workers must use compatible Data Converters to pass operation inputs and results between them.

See [Nexus Payload Encryption & Data Converter](/nexus/security#payload-encryption-data-converter) for details.

---

## Temporal Platform production deployments

**Ready to elevate your durable application into production?**

To take your application to production, you deploy your application code, including your Workflows, Activities, and Workers, on your infrastructure using your existing build, test and deploy tools.

Then you need a production-ready Temporal Service to coordinate the execution of your Workflows and Activities.

You can use Temporal Cloud, a fully-managed platform, or you can self-host the service.

## Use Temporal Cloud

You can let us handle the operations of running the Temporal Service, and focus on your application.
Follow the [Temporal Cloud guide](/cloud) to get started.

<CaptionedImage
    src="/diagrams/basic-platform-topology-cloud.svg"
    title="Connect your application instances to Temporal Cloud"
/>

## Run a Self-hosted Temporal Service

Alternatively, you can run your own production level Temporal Service to orchestrate your durable applications.
Follow the [Self-hosted guide](/self-hosted-guide) to get started.

<CaptionedImage
    src="/diagrams/basic-platform-topology-self-hosted.svg"
    title="Connect your application instances to your self-hosted Temporal Service"
/>

## Worker deployments

Whether you're hosting with Temporal Cloud or on your own, you have control over where to run and scale your Workers.
We provide guidance on [Worker Deployments](/production-deployment/worker-deployments).

---

## Multi-tenant application patterns

Many SaaS providers and large enterprise platform teams use a single Temporal [Namespace](/namespaces) with [per-tenant Task Queues](#1-task-queues-per-tenant-recommended) to power their multi-tenant applications. This approach maximizes resource efficiency while maintaining logical separation between tenants.

This guide covers architectural patterns, design considerations, and practical examples for building multi-tenant applications with Temporal.

## Architectural principles

When designing a multi-tenant Temporal application, follow these principles:

- **Define your tenant model** - Determine what constitutes a tenant in your business (customers, pricing tiers, teams, etc.)
- **Prefer simplicity** - Start with the simplest pattern that meets your needs
- **Understand Temporal limits** - Design within the constraints of your Temporal deployment
- **Test at scale** - Performance testing must drive your capacity decisions
- **Plan for growth** - Consider how you'll onboard new tenants and scale workers

## Architectural patterns

There are three main patterns for multi-tenant applications in Temporal, listed from most to least recommended:

### 1. Task queues per tenant (Recommended)

**Use different [Task Queues](/task-queue) for each tenant's [Workflows](/workflows) and [Activities](/activities).**

This is the recommended pattern for most use cases. Each tenant gets dedicated Task Queue(s), with [Workers](/workers) polling multiple tenant Task Queues in a single process.

**Pros:**
- Strong isolation between tenants
- Efficient resource utilization
- Flexible worker scaling
- Easy to add new tenants
- Can handle thousands of tenants per [Namespace](/namespaces)

**Cons:**
- Requires worker configuration management
- Potential for uneven resource distribution
- Need to prevent "noisy neighbor" issues at the worker level

<RelatedReadContainer>
  <RelatedReadItem path="#task-queue-isolation-pattern" text="Task Queue Isolation Pattern Details" archetype="feature-guide" />
</RelatedReadContainer>

### 2. Shared Workflow Task Queues, separate Activity Task Queues

**Share [Workflow Task Queues](/task-queue) but use different [Activity Task Queues](/task-queue) per tenant.**

Use this pattern when [Workflows](/workflows) are lightweight but [Activities](/activities) have heavy resource requirements or external dependencies that need isolation.

**Pros:**
- Easier worker management than full isolation
- Activity-level tenant isolation
- Good for compute-intensive Activities

**Cons:**
- Less isolation than pattern #1
- Workflow visibility is shared
- More complex to reason about

### 3. Namespace per tenant

**Use a separate [Namespace](/namespaces) for each tenant.**

Only practical for a small number (< 50) of high-value tenants due to operational overhead.

**Pros:**
- Complete isolation between tenants
- Per-tenant rate limiting
- Maximum security

**Cons:**
- Higher operational overhead
- Credential and connectivity management per [Namespace](/namespaces)
- Requires more [Workers](/workers) (minimum 2 per Namespace for high availability)
- Expensive at scale

<RelatedReadContainer>
  <RelatedReadItem path="/evaluate/development-production-features/multi-tenancy#namespace-isolation" text="Namespace Isolation in Temporal Cloud" archetype="cloud-guide" />
</RelatedReadContainer>

## Task Queue isolation pattern

This section details the recommended pattern for most multi-tenant applications.

### Worker design

When a [Worker](/workers) starts up:

1. **Load tenant configuration** - Retrieve the list of tenants this Worker should handle (from config file, API, or database)
2. **Create [Task Queues](/task-queue)** - For each tenant, generate a unique Task Queue name (e.g., `customer-{tenant-id}`)
3. **Register [Workflows](/workflows) and [Activities](/activities)** - Register your Workflow and Activity implementations once, passing the tenant-specific Task Queue name
4. **Poll multiple Task Queues** - A single Worker process polls all assigned tenant Task Queues

```go
// Example: Go worker polling multiple tenant Task Queues
for _, tenant := range assignedTenants {
    taskQueue := fmt.Sprintf("customer-%s", tenant.ID)

    worker := worker.New(client, taskQueue, worker.Options{})
    worker.RegisterWorkflow(YourWorkflow)
    worker.RegisterActivity(YourActivity)
}
```

### Routing requests to Task Queues

Your application needs to route [Workflow](/workflows) starts and other operations to the correct tenant [Task Queue](/task-queue):

```go
// Example: Starting a Workflow for a specific tenant
taskQueue := fmt.Sprintf("customer-%s", tenantID)
workflowOptions := client.StartWorkflowOptions{
    ID:        workflowID,
    TaskQueue: taskQueue,
}
```

Consider creating an API or service that:
- Maps tenant IDs to Task Queue names
- Tracks which [Workers](/workers) are handling which tenants
- Allows both your application and Workers to read the mappings of:
    1. Tenant IDs to Task Queues 
    1. Workers to tenants

### Capacity planning

Key questions to answer through performance testing:

**[Namespace](/namespaces) capacity:**
- How many concurrent [Task Queue](/task-queue) pollers can your Namespace support?
- What are your [Actions Per Second (APS)](/cloud/limits#actions-per-second) limits?
- What are your [Operations Per Second (OPS)](/references/operation-list) limits?

**[Worker](/workers) capacity:**
- How many tenants can a single Worker process handle?
- What are the CPU and memory requirements per tenant?
- How many concurrent [Workflow](/workflows) executions per tenant?
- How many concurrent [Activity](/activities) executions per tenant?

**SDK configuration to tune:**
- `MaxConcurrentWorkflowTaskExecutionSize`
- `MaxConcurrentActivityExecutionSize`
- `MaxConcurrentWorkflowTaskPollers`
- `MaxConcurrentActivityTaskPollers`
- Worker replicas (in Kubernetes deployments)

### Provisioning new tenants

Automate tenant onboarding with a Temporal [Workflow](/workflows):

1. Create a tenant onboarding Workflow that:
   - Validates tenant information
   - Provisions infrastructure
   - Deploys/updates [Worker](/workers) configuration
   - Triggers Worker restarts or scaling
   - Verifies the tenant is operational

2. Store tenant-to-Worker mappings in a database or configuration service

3. Update Worker deployments to pick up new tenant assignments

## Practical example

**Scenario:** A SaaS company has 1,000 customers and expects to grow to 5,000 customers over 3 years. They have 2 [Workflows](/workflows) and ~25 [Activities](/activities) per Workflow. All customers are on the same tier (no segmentation yet).

### Assumptions

| Item | Value |
|------|-------|
| Current customers | 1,000 |
| Workflow Task Queues per customer | 1 |
| Activity Task Queues per customer | 1 |
| Max Task Queue pollers per Namespace | 5,000 |
| SDK concurrent Workflow task pollers | 5 |
| SDK concurrent Activity task pollers | 5 |
| Max concurrent Workflow executions | 200 |
| Max concurrent Activity executions | 200 |

### Capacity calculations

**[Task Queue](/task-queue) poller limits:**
- Each [Worker](/workers) uses 10 pollers per tenant (5 Workflow + 5 Activity)
- Maximum Workers in [Namespace](/namespaces): 5,000 pollers ÷ 10 = **500 Workers**

**Worker capacity:**
- Each Worker can theoretically handle 200 [Workflows](/workflows) and 200 [Activities](/activities) concurrently
- Conservative estimate: **250 tenants per Worker** (accounting for overhead)
- For 1,000 customers: **4 Workers minimum** (plus replicas for HA)
- For 5,000 customers: **20 Workers minimum** (plus replicas for HA)

**Namespace capacity:**
- At 250 tenants per Worker, need 2 Workers per group of tenants (for HA)
- Maximum tenants in Namespace: (500 Workers ÷ 2) × 250 = **62,500 tenants**

:::note
These are theoretical calculations based on SDK defaults. **Always perform load testing** to determine actual capacity for your specific workload. Monitor CPU, memory, and Temporal metrics during testing.

While testing, also pay attention to your [metrics capacity and cardinality](/cloud/metrics/openmetrics/api-reference#managing-high-cardinality).
:::

### Worker assignment strategies

**Option 1: Static configuration**
- Each [Worker](/workers) reads a config file listing assigned tenant IDs
- Simple to implement
- Requires deployment to add tenants

**Option 2: Dynamic API**
- Workers call an API on startup to get assigned tenants
- Workers identified by static ID (1 to N)
- API returns tenant list based on Worker ID
- More flexible, no deployment needed for new tenants

## Best practices

### Monitoring

Track these [metrics](/references/sdk-metrics) per tenant:
- [Workflow completion](/cloud/metrics/openmetrics/metrics-reference#workflow-completion-metrics) rates
- [Activity execution](/cloud/metrics/openmetrics/metrics-reference#task-queue-metrics) rates
- [Task Queue backlog](/cloud/metrics/openmetrics/metrics-reference#task-queue-metrics)
- [Worker resource utilization](/references/sdk-metrics#worker_task_slots_used)
- [Workflow failure rates](/encyclopedia/detecting-workflow-failures)

### Handling noisy neighbors

Even with [Task Queue](/task-queue) isolation, monitor for tenants that:
- Generate excessive load
- Have high failure rates
- Cause [Worker](/workers) resource exhaustion

Strategies:
- Implement per-tenant rate limiting in your application
- Move problematic tenants to dedicated Workers
- Use [Workflow](/workflows)/[Activity](/activities) timeouts aggressively

### Tenant lifecycle

Plan for:
- **Onboarding** - Automated provisioning [Workflow](/workflows)
- **Scaling** - When to add new [Workers](/workers) for growing tenants
- **Offboarding** - Graceful tenant removal and data cleanup
- **Rebalancing** - Redistributing tenants across Workers

### Search Attributes

Use [Search Attributes](/search-attribute) to enable tenant-scoped queries:
```go
// Add tenant ID as a Search Attribute
searchAttributes := map[string]interface{}{
    "TenantId": tenantID,
}
```

This allows filtering [Workflows](/workflows) by tenant in the UI and SDK:
```sql
TenantId = 'customer-123' AND ExecutionStatus = 'Running'
```

## Related resources

<RelatedReadContainer>
  <RelatedReadItem path="/evaluate/development-production-features/multi-tenancy" text="Multi-tenancy Overview" archetype="feature-guide" />
  <RelatedReadItem path="/cloud/limits" text="Temporal Cloud Limits" archetype="cloud-guide" />
  <RelatedReadItem path="/visibility" text="Visibility and Search Attributes" archetype="feature-guide" />
</RelatedReadContainer>

---

## Self-hosted Archival setup

Archival is a feature that automatically backs up [Event Histories](/workflow-execution/event#event-history) and Visibility records from Temporal Service persistence to a custom blob store.

- [How to create a custom Archiver](#custom-archiver)
- [How to set up Archival](#set-up-archival)

Workflow Execution Event Histories are backed up after the [Retention Period](/temporal-service/temporal-server#retention-period) is reached.
Visibility records are backed up immediately after a Workflow Execution reaches a Closed status.

Archival enables Workflow Execution data to persist as long as needed, while not overwhelming the Temporal Service's persistence store.

This feature is helpful for compliance and debugging.

Temporal's Archival feature is considered **experimental** and not subject to normal [versioning and support policy](/temporal-service/temporal-server#versions-and-support).

Archival is not supported when running Temporal through Docker.
It's disabled by default when installing the system manually and when deploying through [helm charts](https://github.com/temporalio/helm-charts/blob/main/charts/temporal/templates/server-configmap.yaml).
It can be enabled in the [config](https://github.com/temporalio/temporal/blob/main/config/development.yaml).

### How to set up Archival {#set-up-archival}

[Archival](/temporal-service/archival) consists of the following elements:

- **Configuration:** Archival is controlled by the [server configuration](https://github.com/temporalio/temporal/blob/main/config/development.yaml#L81) (i.e. the `config/development.yaml` file).
- **Provider:** Location where the data should be archived. Supported providers are S3, GCloud, and the local file system.
- **URI:** Specifies which provider should be used. The system uses the URI schema and path to make the determination.

Take the following steps to set up Archival:

1. [Set up the provider](#providers) of your choice.
2. [Configure Archival](#configuration).
3. [Create a Namespace](#namespace-creation) that uses a valid URI and has Archival enabled.

#### Providers

Temporal directly supports several providers:

- **Local file system**: The [filestore archiver](https://github.com/temporalio/temporal/tree/main/common/archiver/filestore) is used to archive data in the file system of whatever host the Temporal server is running on. In the case of [temporal helm-charts](https://github.com/temporalio/helm-charts), the archive data is stored in the `history` pod. APIs do not function with the filestore archive. This provider is used mainly for local installations and testing and should not be relied on for production environments.
- **Google Cloud**: The [gcloud archiver](https://github.com/temporalio/temporal/tree/main/common/archiver/gcloud) is used to connect and archive data with [Google Cloud](https://cloud.google.com/storage).
- **S3**: The [s3store archiver](https://github.com/temporalio/temporal/tree/main/common/archiver/s3store) is used to connect and archive data with [S3](https://aws.amazon.com/s3).
- **Custom**: If you want to use a provider that is not currently supported, you can [create your own archiver](#custom-archiver) to support it.

Make sure that you save the provider's storage location URI in a place where you can reference it later, because it is passed as a parameter when you [create a Namespace](#namespace-creation).

#### Configuration

Archival configuration is defined in the [`config/development.yaml`](https://github.com/temporalio/temporal/blob/main/config/development.yaml#L93) file.
Let's look at an example configuration:

```yaml