From ae0a0a13477636036ed1d0115c7e54f7898b68a1 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 27 Jan 2026 11:44:19 -0500 Subject: [PATCH 1/8] Standalone Activity concept docs --- docs/encyclopedia/activities/activities.mdx | 13 ++++++---- .../activities/activity-execution.mdx | 5 ++-- .../activities/standalone-activity.mdx | 26 +++++++++++++++++++ .../detecting-activity-failures.mdx | 2 +- sidebars.js | 1 + 5 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 docs/encyclopedia/activities/standalone-activity.mdx diff --git a/docs/encyclopedia/activities/activities.mdx b/docs/encyclopedia/activities/activities.mdx index b3dd08b612..62928fed57 100644 --- a/docs/encyclopedia/activities/activities.mdx +++ b/docs/encyclopedia/activities/activities.mdx @@ -3,7 +3,7 @@ id: activities title: What is a Temporal Activity? sidebar_label: Activities description: - Understand Temporal Activities, including Activity Definitions, Types, Executions, idempotency, cancellations, and + Understand Temporal Activities, including Activity Definitions, Types, Executions, idempotency, cancellations, Standalone Activities, and Local Activities. slug: /activities toc_max_heading_level: 4 @@ -19,7 +19,7 @@ tags: This guide provides a comprehensive overview of Temporal Activities including [Activity Definition](/activity-definition), [Activity Type](/activity-definition#activity-type), -[Activity Execution](/activity-execution), and [Local Activity](/local-activity). +[Activity Execution](/activity-execution), [Standalone Activity](/standalone-activity), and [Local Activity](/local-activity). An Activity is a normal function or method that executes a single, well-defined action (either short or long running), such as calling another service, transcoding a media file, or sending an email message. Activity code can be @@ -34,11 +34,14 @@ Activities are the most common Temporal primitive and encompass small units of w Larger pieces of functionality should be broken up into multiple activities. This makes it easier to do failure recovery, have short timeouts, and be idempotent. -Workflow code orchestrates the execution of Activities, persisting the results. If an Activity Function Execution fails, -any future execution starts from initial state (except -[Heartbeats](/encyclopedia/detecting-activity-failures#activity-heartbeat)). +Workflow code orchestrates the execution of Activities, persisting the results. If an Activity Execution fails, +any future attempt will start from the initial state, unless your code uses ([Heartbeat details payloads](/encyclopedia/detecting-activity-failures#activity-heartbeat)) +for checkpointing (storing state on the server, and using it when resuming subsequent attempts). Activity Functions are executed by Worker Processes. When the Activity Function returns, the Worker sends the results back to the Temporal Service as part of the [ActivityTaskCompleted](/references/events#activitytaskcompleted) Event. The Event is added to the Workflow Execution's Event History. For other Activity-related Events, see [Activity Events](/workflow-execution/event#activity-events). + +If you only want to execute one Activity Function, then you don't need to use a Workflow: you can use your SDK Client to invoke it directly as a [Standalone Activity](/standalone-activity). +This will have lower latency and will result in fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud. \ No newline at end of file diff --git a/docs/encyclopedia/activities/activity-execution.mdx b/docs/encyclopedia/activities/activity-execution.mdx index 5696d66a19..db42273a7c 100644 --- a/docs/encyclopedia/activities/activity-execution.mdx +++ b/docs/encyclopedia/activities/activity-execution.mdx @@ -46,8 +46,9 @@ You can customize [Activity Execution timeouts](/encyclopedia/detecting-activity [retry policies](/encyclopedia/retry-policies). If an Activity Execution fails (because it exhausted all retries, threw a -[non-retryable error](/encyclopedia/retry-policies#non-retryable-errors), or was canceled), the error is returned to the -[Workflow](/workflows), which decides how to handle it. +[non-retryable error](/encyclopedia/retry-policies#non-retryable-errors), or was canceled), the error is returned to your +[Workflow](/workflows) code when it attempts to fetch the Activity result. For [Standalone Activities](/standalone-activity) the error is +returned to the Client when you attempt to fetch the Activity result. :::note diff --git a/docs/encyclopedia/activities/standalone-activity.mdx b/docs/encyclopedia/activities/standalone-activity.mdx new file mode 100644 index 0000000000..2734ca978d --- /dev/null +++ b/docs/encyclopedia/activities/standalone-activity.mdx @@ -0,0 +1,26 @@ +--- +id: standalone-activity +title: Standalone Activity +sidebar_label: Standalone Activity +description: Learn about Standalone Activities in Temporal, their benefits, execution model, and when to use them. +slug: /standalone-activity +toc_max_heading_level: 4 +keywords: + - explanation + - term + - timeouts +tags: + - Concepts + - Activities + - Durable Execution +--- + +## Standalone Activity {#standalone-activity} + +An [Activity Execution](/activity-execution) that is started directly by a [Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a Standalone Activity. + +If you need to orchestrate multiple Activity Executions, then you should use a Workflow. +But if you just need to execute a single Activity, then Standalone Activity will have lower latency and will result in fewer [Billable Actions](/cloud/actions) in Temporal Cloud. + +Standalone Activities support the same retry policies and timeouts as Workflow Activities, and you write your Activity Functions in the same way for both. +In fact, an Activity Function can be executed both as a Standalone Activity and as a Workflow Activity. diff --git a/docs/encyclopedia/detecting-activity-failures.mdx b/docs/encyclopedia/detecting-activity-failures.mdx index 9a2355d719..3213dd59bb 100644 --- a/docs/encyclopedia/detecting-activity-failures.mdx +++ b/docs/encyclopedia/detecting-activity-failures.mdx @@ -185,7 +185,7 @@ Activity Heartbeats are implemented within the Activity Definition. Custom progress information can be included in the Heartbeat which can then be used by the Activity Execution should a retry occur. An Activity Heartbeat can be recorded as often as needed (e.g. once a minute or every loop iteration). -It is often a good practice to Heartbeat on anything but the shortest Activity Function Execution. +It is often a good practice to Heartbeat on anything but the shortest Activity Execution. Temporal SDKs control the rate at which Heartbeats are sent to the Temporal Service. Heartbeating is not required from [Local Activities](/local-activity), and does nothing. diff --git a/sidebars.js b/sidebars.js index 567a21a3fd..ea1b7ebe5c 100644 --- a/sidebars.js +++ b/sidebars.js @@ -704,6 +704,7 @@ module.exports = { items: [ 'encyclopedia/activities/activity-definition', 'encyclopedia/activities/activity-execution', + 'encyclopedia/activities/standalone-activity', 'encyclopedia/activities/local-activity', ], }, From 89da3f59e2cca6de4edd17d628f843d26700165c Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Tue, 27 Jan 2026 18:02:57 -0500 Subject: [PATCH 2/8] Simplify --- docs/encyclopedia/activities/activities.mdx | 4 ++-- docs/encyclopedia/activities/standalone-activity.mdx | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/encyclopedia/activities/activities.mdx b/docs/encyclopedia/activities/activities.mdx index 62928fed57..5629c7cb5f 100644 --- a/docs/encyclopedia/activities/activities.mdx +++ b/docs/encyclopedia/activities/activities.mdx @@ -43,5 +43,5 @@ back to the Temporal Service as part of the [ActivityTaskCompleted](/references/ Event is added to the Workflow Execution's Event History. For other Activity-related Events, see [Activity Events](/workflow-execution/event#activity-events). -If you only want to execute one Activity Function, then you don't need to use a Workflow: you can use your SDK Client to invoke it directly as a [Standalone Activity](/standalone-activity). -This will have lower latency and will result in fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud. \ No newline at end of file +If you only want to execute one Activity Function, then you don't need to use a Workflow: you can +use your SDK Client to invoke it directly as a [Standalone Activity](/standalone-activity). diff --git a/docs/encyclopedia/activities/standalone-activity.mdx b/docs/encyclopedia/activities/standalone-activity.mdx index 2734ca978d..14f3ef2a01 100644 --- a/docs/encyclopedia/activities/standalone-activity.mdx +++ b/docs/encyclopedia/activities/standalone-activity.mdx @@ -19,8 +19,12 @@ tags: An [Activity Execution](/activity-execution) that is started directly by a [Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a Standalone Activity. -If you need to orchestrate multiple Activity Executions, then you should use a Workflow. -But if you just need to execute a single Activity, then Standalone Activity will have lower latency and will result in fewer [Billable Actions](/cloud/actions) in Temporal Cloud. +If you need to orchestrate multiple Activity Executions, then you should use a Workflow. But if you +just need to execute a single Activity, then you can use a Standalone Activity. This will result in +fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud. If your Activity +Execution is short-lived, then you will also notice lower latency, since there are fewer worker +round-trips than when executing the Activity in a Workflow. -Standalone Activities support the same retry policies and timeouts as Workflow Activities, and you write your Activity Functions in the same way for both. -In fact, an Activity Function can be executed both as a Standalone Activity and as a Workflow Activity. +Standalone Activities support the same retry policies and timeouts as Workflow Activities, and you +write your Activity Functions in the same way for both. In fact, an Activity Function can be +executed both as a Standalone Activity and as a Workflow Activity. From 369e0da671400662c9e3d2ccb5e5e02c5c649f50 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Tue, 10 Feb 2026 15:12:34 -0600 Subject: [PATCH 3/8] job queue one pager draft --- .../job-queue.mdx | 51 +++++++++++++++++++ sidebars.js | 1 + 2 files changed, 52 insertions(+) create mode 100644 docs/evaluate/development-production-features/job-queue.mdx diff --git a/docs/evaluate/development-production-features/job-queue.mdx b/docs/evaluate/development-production-features/job-queue.mdx new file mode 100644 index 0000000000..b11e787f78 --- /dev/null +++ b/docs/evaluate/development-production-features/job-queue.mdx @@ -0,0 +1,51 @@ +--- +id: job-queue +title: Job Queue +sidebar_label: Job Queue +description: Standalone Activities adds the ability to execute any Temporal Activity as a top-level primitive without the full overhead of a Workflow. +keywords: + - job queue + - standalone activities + - background jobs + - durable execution +tags: + - Features + - Standalone Activities +--- + +## What is a Job Queue in Temporal? + +A job is a single, discrete unit of work that runs asynchronously in the background such as sending an email, processing a webhook, syncing data, or executing a long-running task. + +A job queue is the system that manages these jobs: accepting work, dispatching it to workers, retrying on failure, and providing visibility into what's running and what failed. + +**Standalone Activities are Temporal's job queue.** + +They let you use Temporal Activities as background jobs, in addition to using the same Activities as steps inside a Workflow. You write an Activity once and can run it either as a background job or as part of a multi-step Workflow. + +Temporal provides stronger guarantees, better visibility, and more control than traditional job queues - while remaining cost-effective for high-volume use cases and offering a clean upgrade path to multi-step workflow orchestration. + +### Overview + +Standalone Activities add the ability to execute any Temporal Activity as a top-level Activity Execution for durable job processing. + +#### Unified programming model & worker deployment + +- Write an Activity once and use it anywhere - with a unified Activity programming model +- Optional heartbeats support checkpointing for long-running jobs +- Deploy to an Activity Worker once, and invoke standalone or from within a Workflow + +#### Execution lifecycle + +- Jobs are submitted as Standalone Activity Executions +- Each job is durably persisted with Temporal reliability, so jobs are not lost +- Jobs are scheduled with priority, fairness, deduplication and no head of line blocking +- Workers poll task queues and execute Activities (you run your own Workers) +- Temporal ensures retries, timeouts, and exponential backoff policy is enforced + +#### Observability & lifecycle controls + +- Full job visibility (list, search) with detailed execution state, retry count, errors & results +- OpenMetrics support +- Lifecycle controls: cancel, pause, unpause, reset, terminate +- Manual completion for external integrations & on-call management diff --git a/sidebars.js b/sidebars.js index ea1b7ebe5c..df9870cbdf 100644 --- a/sidebars.js +++ b/sidebars.js @@ -23,6 +23,7 @@ module.exports = { }, items: [ 'evaluate/development-production-features/core-application', + 'evaluate/development-production-features/job-queue', 'evaluate/development-production-features/failure-detection', 'evaluate/development-production-features/throughput-composability', 'evaluate/development-production-features/nexus', From 7b8467e1486903c5f9d418675472d8428339be28 Mon Sep 17 00:00:00 2001 From: Phil Prasek Date: Tue, 24 Feb 2026 17:02:59 -0800 Subject: [PATCH 4/8] refine standalone activity encyclopedia and evaluate pages Signed-off-by: Phil Prasek --- docs/encyclopedia/activities/activities.mdx | 6 +- .../activities/standalone-activity.mdx | 69 ++++++++++++++++++- .../job-queue.mdx | 13 +++- sidebars.js | 4 +- 4 files changed, 82 insertions(+), 10 deletions(-) diff --git a/docs/encyclopedia/activities/activities.mdx b/docs/encyclopedia/activities/activities.mdx index 5629c7cb5f..b2683ca9e3 100644 --- a/docs/encyclopedia/activities/activities.mdx +++ b/docs/encyclopedia/activities/activities.mdx @@ -3,8 +3,8 @@ id: activities title: What is a Temporal Activity? sidebar_label: Activities description: - Understand Temporal Activities, including Activity Definitions, Types, Executions, idempotency, cancellations, Standalone Activities, and - Local Activities. + Understand Temporal Activities, including Activity Definitions, Types, Executions, idempotency, cancellations, Local Activities, and + Standalone Activities. slug: /activities toc_max_heading_level: 4 keywords: @@ -19,7 +19,7 @@ tags: This guide provides a comprehensive overview of Temporal Activities including [Activity Definition](/activity-definition), [Activity Type](/activity-definition#activity-type), -[Activity Execution](/activity-execution), [Standalone Activity](/standalone-activity), and [Local Activity](/local-activity). +[Activity Execution](/activity-execution), [Local Activity](/local-activity), and [Standalone Activity](/standalone-activity). An Activity is a normal function or method that executes a single, well-defined action (either short or long running), such as calling another service, transcoding a media file, or sending an email message. Activity code can be diff --git a/docs/encyclopedia/activities/standalone-activity.mdx b/docs/encyclopedia/activities/standalone-activity.mdx index 14f3ef2a01..880b96f06f 100644 --- a/docs/encyclopedia/activities/standalone-activity.mdx +++ b/docs/encyclopedia/activities/standalone-activity.mdx @@ -6,6 +6,7 @@ description: Learn about Standalone Activities in Temporal, their benefits, exec slug: /standalone-activity toc_max_heading_level: 4 keywords: + - standalone activity - explanation - term - timeouts @@ -15,16 +16,78 @@ tags: - Durable Execution --- -## Standalone Activity {#standalone-activity} +:::tip SUPPORT, STABILITY, and DEPENDENCY INFO -An [Activity Execution](/activity-execution) that is started directly by a [Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a Standalone Activity. +Standalone Activities are available as a [Pre-release](/evaluate/development-production-features/release-stages#pre-release) feature in [Temporal Cloud](#temporal-cloud-support) and in a [special release](#temporal-cli-support) of the Temporal CLI. + +::: + +See [limitations](#pre-release-limitations) below. + +## What is a Standalone Activity? {#standalone-activity} + +A top-level [Activity Execution](/activity-execution) that is started directly by a [Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a Standalone Activity. If you need to orchestrate multiple Activity Executions, then you should use a Workflow. But if you just need to execute a single Activity, then you can use a Standalone Activity. This will result in -fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud. If your Activity +fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud than using a Workflow to run a single Activity. If your Activity Execution is short-lived, then you will also notice lower latency, since there are fewer worker round-trips than when executing the Activity in a Workflow. Standalone Activities support the same retry policies and timeouts as Workflow Activities, and you write your Activity Functions in the same way for both. In fact, an Activity Function can be executed both as a Standalone Activity and as a Workflow Activity. + +## Use cases + +Standalone Activities can be used for [durable job processing use cases](/evaluate/development-production-features/job-queue) such as sending an email, processing a webhook, syncing data, or executing a single function reliably with built-in retries and timeouts. + +## Key features +- Execute any Temporal Activity as a top-level primitive without the overhead of a Workflow +- Native async job processing model: schedule -> dispatch -> process -> result +- No head-of-line blocking - a slow job doesn’t block the dispatch of other Tasks +- Arbitrary length jobs with heartbeats for liveness and checkpointing progress +- At-least-once execution by default with native retry policy and timeouts +- At-most-once execution if retry max attempts is 1 +- Addressable - get an Activity ID / Run ID and get the result, cancel, and terminate +- Deduplication - with conflict policy: (USE_EXISTING, …), reuse policy: (REJECT_DUPLICATES, …) +- Separate ID space from Workflows - Standalone Activities are a different kind of top-level execution +- Priority and fairness - multi-tenant fairness, weighted priority tiers, and safeguards against starvation of lower-weighted tasks +- Visibility - list Activity Executions and view status, retry count, and last error +- Manual completion by ID (or token): ignore activity return and wait for external completion +- Activity metrics - including counts for success, failure, timeout, and cancel +- Dual use - execute Activities within a Workflow or standalone with no Worker code changes + +## Pre-release limitations + +The pre-release of Standalone Activities is recommended for experimental use only and has some known limitations. + +General limitations: +- Not suitable for production use cases during Pre-release +- Delete, pause, reset, and update options are not supported yet +- TerminateExisting conflict policy and TerminateIfRunning reuse policy are not supported yet +- Heartbeat timeout must be explicitly set by the caller if using heartbeats in an Activity definition, otherwise it will fail immediately + +Temporal Cloud limitations: +- Standalone Activities are free for evaluation purposes during Pre-release, so we reserve the right to limit usage if it exceeds a reasonable amount +- 1 day max retention for Standalone Activities +- We recommend enabling Standalone Activities on a new namespace for dev/test experimental use only + +## Temporal CLI support + +A [special release of the Temporal CLI](https://TODO) supports Standalone Activities during Pre-release: +- The `temporal activity` subcommand supports Standalone Activities with commands including: `start`, `result`, and `list` +- Temporal Dev Server has Standalone Activities enabled by default in this special CLI release for local testing + +## Temporal Cloud support + +Contact your account team to enable Standalone Activities in Temporal Cloud as a Pre-release feature. + +## Get started + +:::tip RESOURCES + +- [Go SDK - Standalone Activities quick start and code sample](/develop/go/standalone-activities) +- [Python SDK - Standalone Activities quick start and code sample](/develop/python/standalone-activities) + + ::: diff --git a/docs/evaluate/development-production-features/job-queue.mdx b/docs/evaluate/development-production-features/job-queue.mdx index b11e787f78..b1c9b6a086 100644 --- a/docs/evaluate/development-production-features/job-queue.mdx +++ b/docs/evaluate/development-production-features/job-queue.mdx @@ -5,6 +5,7 @@ sidebar_label: Job Queue description: Standalone Activities adds the ability to execute any Temporal Activity as a top-level primitive without the full overhead of a Workflow. keywords: - job queue + - job system - standalone activities - background jobs - durable execution @@ -13,9 +14,11 @@ tags: - Standalone Activities --- -## What is a Job Queue in Temporal? +import { RelatedReadContainer, RelatedReadItem } from '@site/src/components'; -A job is a single, discrete unit of work that runs asynchronously in the background such as sending an email, processing a webhook, syncing data, or executing a long-running task. +## What is a Job Queue? + +A job is a single, discrete unit of work that runs asynchronously in the background such as sending an email, processing a webhook, syncing data, or executing a single function reliably. A job queue is the system that manages these jobs: accepting work, dispatching it to workers, retrying on failure, and providing visibility into what's running and what failed. @@ -49,3 +52,9 @@ Standalone Activities add the ability to execute any Temporal Activity as a top- - OpenMetrics support - Lifecycle controls: cancel, pause, unpause, reset, terminate - Manual completion for external integrations & on-call management + + + + + + \ No newline at end of file diff --git a/sidebars.js b/sidebars.js index df9870cbdf..9d7b97a92f 100644 --- a/sidebars.js +++ b/sidebars.js @@ -23,7 +23,6 @@ module.exports = { }, items: [ 'evaluate/development-production-features/core-application', - 'evaluate/development-production-features/job-queue', 'evaluate/development-production-features/failure-detection', 'evaluate/development-production-features/throughput-composability', 'evaluate/development-production-features/nexus', @@ -37,6 +36,7 @@ module.exports = { 'evaluate/development-production-features/cloud-automation', 'evaluate/development-production-features/low-latency', 'evaluate/development-production-features/multi-tenancy', + 'evaluate/development-production-features/job-queue', { type: 'category', label: 'Product release stages', @@ -705,8 +705,8 @@ module.exports = { items: [ 'encyclopedia/activities/activity-definition', 'encyclopedia/activities/activity-execution', - 'encyclopedia/activities/standalone-activity', 'encyclopedia/activities/local-activity', + 'encyclopedia/activities/standalone-activity', ], }, { From ab0504714b1902d74efacdb2faf14c1b8d4ad436 Mon Sep 17 00:00:00 2001 From: Jwahir Sundai Date: Mon, 23 Feb 2026 16:02:57 -0600 Subject: [PATCH 5/8] Python docs --- docs/develop/python/index.mdx | 8 + docs/develop/python/standalone-activities.mdx | 282 ++++++++++++++++++ sidebars.js | 1 + static/img/standalone-activities-ui-nav.png | Bin 0 -> 63952 bytes 4 files changed, 291 insertions(+) create mode 100644 docs/develop/python/standalone-activities.mdx create mode 100644 static/img/standalone-activities-ui-nav.png diff --git a/docs/develop/python/index.mdx b/docs/develop/python/index.mdx index a5304efaa5..2d8e51bf8e 100644 --- a/docs/develop/python/index.mdx +++ b/docs/develop/python/index.mdx @@ -49,6 +49,14 @@ Connect to a Temporal Service and start a Workflow Execution. - [Connect to Temporal Cloud](/develop/python/temporal-client#connect-to-temporal-cloud) - [Start a Workflow Execution](/develop/python/temporal-client#start-workflow-execution) +## [Standalone Activities](/develop/python/standalone-activities) + +Execute Activities independently without a Workflow using the Temporal Client. + +- [How to execute a Standalone Activity](/develop/python/standalone-activities#execute-activity) +- [How to get the result of a Standalone Activity](/develop/python/standalone-activities#get-activity-result) +- [How to get a handle to an existing Standalone Activity](/develop/python/standalone-activities#get-activity-handle) + ## [Python SDK Sandbox](/develop/python/python-sdk-sandbox) Use third-party Python modules without non-deterministic behavior. diff --git a/docs/develop/python/standalone-activities.mdx b/docs/develop/python/standalone-activities.mdx new file mode 100644 index 0000000000..dec62d813a --- /dev/null +++ b/docs/develop/python/standalone-activities.mdx @@ -0,0 +1,282 @@ +--- +id: standalone-activities +title: Standalone Activities - Python SDK +sidebar_label: Standalone Activities +toc_max_heading_level: 4 +keywords: + - standalone activity + - activity execution + - execute activity + - activity handle + - list activities + - count activities + - python sdk +tags: + - Activities + - Temporal Client + - Python SDK + - Temporal SDKs +description: Execute Activities independently without a Workflow using the Temporal Python SDK. +--- + +:::tip SUPPORT, STABILITY, and DEPENDENCY INFO + +Temporal Python SDK support for Standalone Activities is at +[Pre-release](/evaluate/development-production-features/release-stages#pre-release). + +All APIs are experimental and may be subject to backwards-incompatible changes. + +::: + +Standalone Activities are Activity Executions that run independently, without being orchestrated by a Workflow. Instead +of starting an Activity from within a Workflow Definition, you start a Standalone Activity directly from a Temporal +Client. + +The way you write the Activity Definition and register it with a Worker is identical to [Workflow +Activities](./core-application.mdx#develop-activities). The only difference is that you execute a +Standalone Activity directly from your Temporal Client. + +This page covers the following: + +- [Run the Temporal Development Server with Standalone Activities enabled](#run-the-temporal-standalone-activity-development-server) +- [Run a worker with the activity registered](#run-worker) +- [Execute a Standalone Activity](#execute-activity) +- [Start a Standalone Activity without waiting for the result](#start-activity) +- [Get a handle to an existing Standalone Activity](#get-activity-handle) +- [Wait for the result of a Standalone Activity](#get-activity-result) +- [List Standalone Activities](#list-activities) +- [Count Standalone Activities](#count-activities) + +:::note + +This documentation uses source code derived from the [Python sample](https://github.com/temporalio/samples-python/blob/main/hello/hello_standalone_activity.py). + + + +::: + +## Run the Temporal Development Server with Standalone Activities enabled {#run-the-temporal-standalone-activity-development-server} + +Prerequisites: + +- Install the latest Temporal CLI + + 🚧 Please build from development branch: https://github.com/temporalio/cli/tree/release/v1.6.x-standalone-activity +- [Install the latest Temporal Python SDK](https://docs.temporal.io/develop/python/set-up-your-local-python#install-the-temporal-python-sdk) + +The first step in running a Standalone Activity involves starting a Temporal server. + +```bash +temporal server start-dev +``` + +This command automatically starts the Temporal development server with the Web UI, and creates the `default` Namespace. +It uses an in-memory database, so do not use it for real use cases. + +The Temporal Server will now be available for client connections on `localhost:7233`, and the +Temporal Web UI will now be accessible at [http://localhost:8233](http://localhost:8233). Standalone +Activities are available from the nav bar item located towards the top left of the page: + +Standalone Activities Web UI nav bar item + +## Write an Activity Function {#write-activity} + +An Activity Definition in the Temporal Python SDK is just a normal function with the +`@activity.defn` decorator. It can optionally be an `async def`. The way you write a Standalone +Activity is identical to how you write an Activity to be orchestrated by a Workflow. In fact, an +Activity can be executed both as a Standalone Activity and as a Workflow Activity. + +To see this code in a working example, see the [Standalone Activity +sample](https://github.com/temporalio/samples-python/blob/main/hello/hello_standalone_activity.py). + + +```python +# my_activity.py +from dataclasses import dataclass + +from temporalio import activity + + +@dataclass +class ComposeGreetingInput: + greeting: str + name: str + + +@activity.defn +async def compose_greeting(input: ComposeGreetingInput) -> str: + activity.logger.info("Running activity with parameter %s" % input) + return f"{input.greeting}, {input.name}!" +``` + +## Run a Worker with the Activity registered {#run-worker} + +Running a Worker for Standalone Activities is the same as running a Worker for Workflow Activities β€” +you create a Worker, register the Activity, and run the Worker. The Worker doesn't need to know +whether the Activity will be invoked from a Workflow or as a Standalone Activity. See [How to run a +Worker](/develop/python/core-application#run-a-dev-worker) for more details on Worker setup and +configuration options. + +To see this code in a working example, see the [Standalone Activity +sample](https://github.com/temporalio/samples-python/blob/main/hello/hello_standalone_activity.py). + +```python +import asyncio + +from my_activity import compose_greeting +from temporalio.client import Client +from temporalio.worker import Worker + + +async def main(): + client = await Client.connect("localhost:7233") + worker = Worker( + client, + task_queue="hello-standalone-activity-task-queue", + activities=[compose_greeting], + ) + await worker.run() + + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## Execute a Standalone Activity {#execute-activity} + +Use +[`client.execute_activity()`](https://python.temporal.io/temporalio.client.Client.html#execute_activity) +to execute a Standalone Activity. Call this from your application code, not from inside a Workflow +Definition. This durably enqueues your Standalone Activity in the Temporal Server, waits for it to +be executed on your Worker, and then fetches the result: + +```python +import asyncio +from datetime import timedelta + +from temporalio.client import Client + +from my_activity import ComposeGreetingInput, compose_greeting + + +async def my_application(): + client = await Client.connect("localhost:7233") + + result = await client.execute_activity( + compose_greeting, + args=[ComposeGreetingInput("Hello", "World")], + id="my-standalone-activity-id", + task_queue="hello-standalone-activity-task-queue", + start_to_close_timeout=timedelta(seconds=10), + ) + print(f"Activity result: {result}") + + +if __name__ == "__main__": + asyncio.run(my_application()) +``` + + +## Start a Standalone Activity without waiting for the result {#start-activity} + +Starting a Standalone Activity means sending a request to the Temporal Server to durably enqueue +your Activity job, without waiting for it to be executed by your Worker. + +Use +[`client.start_activity()`](https://python.temporal.io/temporalio.client.Client.html#start_activity) +to start your Standalone Activity and get a handle: + +```python +activity_handle = await client.start_activity( + compose_greeting, + args=[ComposeGreetingInput("Hello", "World")], + id="my-standalone-activity-id", + task_queue="hello-standalone-activity-task-queue", + start_to_close_timeout=timedelta(seconds=10), +) +``` + +You can also use `client.get_activity_handle()` to create a handle to a previously started Standalone Activity: + +```python +activity_handle = client.get_activity_handle( + activity_id="my-standalone-activity-id", + activity_run_id="the-run-id", +) +``` + +You can now use the handle to wait for the result, describe, cancel, or terminate the Activity. + +## Wait for the result of a Standalone Activity {#get-activity-result} + +Under the hood, calling `client.execute_activity()` is the same as calling +[`client.start_activity()`](https://python.temporal.io/temporalio.client.Client.html#start_activity) +to durably enqueue the Standalone Activity, and then calling `await activity_handle.result()` to +wait for the activity to be executed and fetch the result: + +```python +activity_result = await activity_handle.result() +``` + + +## List Standalone Activities {#list-activities} + +Use +[`client.list_activities()`](https://python.temporal.io/temporalio.client.Client.html#list_activities) +to list Standalone Activity Executions that match a [List Filter](/list-filter) query. The result is +an async iterator that yields ActivityExecution entries: + +```python +import asyncio + +from temporalio.client import Client + + +async def my_application(): + client = await Client.connect("localhost:7233") + + activities = await client.list_activities( + query="TaskQueue = 'my-task-queue'", + ) + + async for info in activities: + print( + f"ActivityID: {info.activity_id}, Type: {info.activity_type}, Status: {info.status}" + ) + + +if __name__ == "__main__": + asyncio.run(my_application()) +``` + +The query parameter accepts the same [List Filter](/list-filter) syntax used for [Workflow +Visibility](/visibility). For example, "ActivityType = 'MyActivity' AND Status = 'Running'". + + +## Count Standalone Activities {#count-activities} + +Use [`client.count_activities()`](https://python.temporal.io/temporalio.client.Client.html#count_activities) to count +Standalone Activity Executions that match a [List Filter](/list-filter) query. + +```python +import asyncio + +from temporalio.client import Client + + +async def my_application(): + client = await Client.connect("localhost:7233") + + resp = await client.count_activities( + query="TaskQueue = 'my-task-queue'", + ) + + print("Total activities:", resp.count) + + for group in resp.groups: + print(f"Group {group.group_values}: {group.count}") + + +if __name__ == "__main__": + asyncio.run(my_application()) +``` diff --git a/sidebars.js b/sidebars.js index 9d7b97a92f..6a19646ab6 100644 --- a/sidebars.js +++ b/sidebars.js @@ -194,6 +194,7 @@ module.exports = { 'develop/python/set-up-your-local-python', 'develop/python/core-application', 'develop/python/temporal-client', + 'develop/python/standalone-activities', 'develop/python/python-sdk-sandbox', 'develop/python/python-sdk-sync-vs-async', 'develop/python/testing-suite', diff --git a/static/img/standalone-activities-ui-nav.png b/static/img/standalone-activities-ui-nav.png new file mode 100644 index 0000000000000000000000000000000000000000..733e4f6f2e8c3d81e351a5ce4efb26babe854a6f GIT binary patch literal 63952 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 Date: Thu, 26 Feb 2026 20:41:34 -0500 Subject: [PATCH 6/8] Go docs --- docs/develop/go/index.mdx | 8 + docs/develop/go/standalone-activities.mdx | 443 ++++++++++++++++++++++ sidebars.js | 1 + 3 files changed, 452 insertions(+) create mode 100644 docs/develop/go/standalone-activities.mdx diff --git a/docs/develop/go/index.mdx b/docs/develop/go/index.mdx index 15723c7de2..f0152a6a28 100644 --- a/docs/develop/go/index.mdx +++ b/docs/develop/go/index.mdx @@ -96,6 +96,14 @@ Complete Activities asynchronously. - [How to asynchronously complete an Activity](/develop/go/asynchronous-activity-completion) +## [Standalone Activities](/develop/go/standalone-activities) + +Execute Activities independently without a Workflow using the Temporal Client. + +- [How to execute a Standalone Activity](/develop/go/standalone-activities#execute-activity) +- [How to get the result of a Standalone Activity](/develop/go/standalone-activities#get-activity-result) +- [How to get a handle to an existing Standalone Activity](/develop/go/standalone-activities#get-activity-handle) + ## [Versioning](/develop/go/versioning) Change Workflow Definitions without causing non-deterministic behavior in running Workflows. diff --git a/docs/develop/go/standalone-activities.mdx b/docs/develop/go/standalone-activities.mdx new file mode 100644 index 0000000000..f7872a201d --- /dev/null +++ b/docs/develop/go/standalone-activities.mdx @@ -0,0 +1,443 @@ +--- +id: standalone-activities +title: Standalone Activities - Go SDK +sidebar_label: Standalone Activities +toc_max_heading_level: 4 +keywords: + - standalone activity + - activity execution + - execute activity + - activity handle + - list activities + - count activities + - go sdk +tags: + - Activities + - Temporal Client + - Go SDK + - Temporal SDKs +description: Execute Activities independently without a Workflow using the Temporal Go SDK. +--- + +:::tip SUPPORT, STABILITY, and DEPENDENCY INFO + +Temporal Go SDK support for Standalone Activities is at +[Pre-release](/evaluate/development-production-features/release-stages#pre-release). + +All APIs are experimental and may be subject to backwards-incompatible changes. + +::: + +Standalone Activities are Activity Executions that run independently, without being orchestrated by a Workflow. Instead +of starting an Activity from within a Workflow Definition using `workflow.ExecuteActivity()`, you start a Standalone +Activity directly from a Temporal Client using `client.ExecuteActivity()`. + +The Activity definition and Worker registration are identical to regular Activities, and only the execution path +differs. + +This page covers the following: + +- [Run the Temporal Development Server with Standalone Activities enabled](#run-the-temporal-standalone-activity-development-server) +- [Define your Activity](#define-activity) +- [Run a Worker with the Activity registered](#run-worker) +- [Execute a Standalone Activity](#execute-activity) +- [Get the result of a Standalone Activity](#get-activity-result) +- [Get a handle to an existing Standalone Activity](#get-activity-handle) +- [List Standalone Activities](#list-activities) +- [Count Standalone Activities](#count-activities) +- [Run Standalone Activities with Temporal Cloud](#run-standalone-activities-temporal-cloud) + +:::note + +This documentation uses source code from the +[Go sample](https://github.com/temporalio/samples-go/tree/main/standalone-activity/helloworld). + +::: + +## Run the Temporal Development Server with Standalone Activities enabled {#run-the-temporal-standalone-activity-development-server} + +Prerequisites: + +- Install the latest Temporal CLI + + 🚧 Please build from development branch: https://github.com/temporalio/cli/tree/release/v1.6.x-standalone-activity +- [Install the latest Temporal Go SDK](https://docs.temporal.io/develop/go/core-application#install-a-temporal-sdk) + (v1.40.0 or higher recommended) + +The first step in running a Standalone Activity involves starting a Temporal server. + +``` +temporal server start-dev +``` + +This command automatically starts the Temporal development server with the Web UI, and creates the `default` Namespace. +It uses an in-memory database, so do not use it for real use cases. + +The Temporal Server should now be available for client connections on `localhost:7233`, and the +Temporal Web UI should now be accessible at [http://localhost:8233](http://localhost:8233). Standalone +Activities are available from the nav bar item located towards the top left of the page: + +Standalone Activities Web UI nav bar item + +Clone the [samples-go](https://github.com/temporalio/samples-go) repository to follow along: + +``` +git clone https://github.com/temporalio/samples-go.git +cd samples-go +``` + +## Define your Activity {#define-activity} + +Define your Activity in a shared file so that both the Worker and starter can reference it. + +The sample project is structured as follows: + +``` +standalone-activity/helloworld/ +β”œβ”€β”€ activity.go +β”œβ”€β”€ worker/ +β”‚ └── main.go +└── starter/ + └── main.go +``` + +[standalone-activity/helloworld/activity.go](https://github.com/temporalio/samples-go/blob/main/standalone-activity/helloworld/activity.go) + +```go +package helloworld + +import ( + "context" + "go.temporal.io/sdk/activity" +) + +func Activity(ctx context.Context, name string) (string, error) { + logger := activity.GetLogger(ctx) + logger.Info("Activity", "name", name) + return "Hello " + name + "!", nil +} +``` + +## Run a Worker with the Activity registered {#run-worker} + +Running a Worker for Standalone Activities is the same as running a Worker for Workflow-driven Activities β€” you create a +Worker, register the Activity, and call `Run()`. The Worker doesn't need to know whether the Activity will be invoked +from a Workflow or as a Standalone Activity. + +See [How to develop a Worker in Go](/develop/go/core-application#develop-worker) for more details on Worker setup and +configuration options. + +[standalone-activity/helloworld/worker/main.go](https://github.com/temporalio/samples-go/blob/main/standalone-activity/helloworld/worker/main.go) + +```go +package main + +import ( + "github.com/temporalio/samples-go/standalone-activity/helloworld" + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/contrib/envconfig" + "go.temporal.io/sdk/worker" + "log" +) + +func main() { + c, err := client.Dial(envconfig.MustLoadDefaultClientOptions()) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + w := worker.New(c, "standalone-activity-helloworld", worker.Options{}) + + w.RegisterActivity(helloworld.Activity) + + err = w.Run(worker.InterruptCh()) + if err != nil { + log.Fatalln("Unable to start worker", err) + } +} +``` + +To run the Worker: + +``` +go run standalone-activity/helloworld/worker/main.go +``` + +## Execute a Standalone Activity {#execute-activity} + +Use [`client.ExecuteActivity()`](https://pkg.go.dev/go.temporal.io/sdk/client#Client) to start a Standalone Activity +Execution. This is called from application code (for example, a starter program), not from inside a Workflow Definition. + +`ExecuteActivity` returns an [`ActivityHandle`](https://pkg.go.dev/go.temporal.io/sdk/client#ActivityHandle) that you +can use to get the result, describe, cancel, or terminate the Activity. + +The following starter program demonstrates how to execute a Standalone Activity, get its result, list activities, and +count activities: + +[standalone-activity/helloworld/starter/main.go](https://github.com/temporalio/samples-go/blob/main/standalone-activity/helloworld/starter/main.go) + +```go +package main + +import ( + "context" + "github.com/temporalio/samples-go/standalone-activity/helloworld" + "go.temporal.io/sdk/client" + "go.temporal.io/sdk/contrib/envconfig" + "log" + "time" +) + +func main() { + c, err := client.Dial(envconfig.MustLoadDefaultClientOptions()) + if err != nil { + log.Fatalln("Unable to create client", err) + } + defer c.Close() + + activityOptions := client.StartActivityOptions{ + ID: "standalone_activity_helloworld_ActivityID", + TaskQueue: "standalone-activity-helloworld", + ScheduleToCloseTimeout: 10 * time.Second, + } + + handle, err := c.ExecuteActivity(context.Background(), activityOptions, helloworld.Activity, "Temporal") + if err != nil { + log.Fatalln("Unable to execute activity", err) + } + + log.Println("Started standalone activity", "ActivityID", handle.GetID(), "RunID", handle.GetRunID()) + + var result string + err = handle.Get(context.Background(), &result) + if err != nil { + log.Fatalln("Unable get standalone activity result", err) + } + log.Println("Activity result:", result) + + resp, err := c.ListActivities(context.Background(), client.ListActivitiesOptions{ + Query: "TaskQueue = 'standalone-activity-helloworld'", + }) + if err != nil { + log.Fatalln("Unable to list activities", err) + } + + log.Println("ListActivity results") + for info, err := range resp.Results { + if err != nil { + log.Fatalln("Error iterating activities", err) + } + log.Printf("\tActivityID: %s, Type: %s, Status: %v\n", + info.ActivityID, info.ActivityType, info.Status) + } + + resp1, err := c.CountActivities(context.Background(), client.CountActivitiesOptions{ + Query: "TaskQueue = 'standalone-activity-helloworld'", + }) + if err != nil { + log.Fatalln("Unable to count activities", err) + } + + log.Println("Total activities:", resp1.Count) +} +``` + +You can pass the Activity as either a function reference or a string Activity type name: + +```go +handle, err := c.ExecuteActivity(ctx, options, helloworld.Activity, "arg1") + +// Using a string type name +handle, err := c.ExecuteActivity(ctx, options, "Activity", "arg1") +``` + +`client.StartActivityOptions` requires `ID`, `TaskQueue`, and at least one of `ScheduleToCloseTimeout` or +`StartToCloseTimeout`. See [`StartActivityOptions`](https://pkg.go.dev/go.temporal.io/sdk/client#StartActivityOptions) +in the API reference for the full set of options. + +To run the starter (in a separate terminal from the Worker): + +``` +go run standalone-activity/helloworld/starter/main.go +``` + +## Get the result of a Standalone Activity {#get-activity-result} + +Use `ActivityHandle.Get()` to block until the Activity completes and retrieve its result. This is analogous to calling +`Get()` on a `WorkflowRun`. + +```go +var result string +err = handle.Get(context.Background(), &result) +if err != nil { + log.Fatalln("Activity failed", err) +} +log.Println("Activity result:", result) +``` + +If the Activity completed successfully, the result is deserialized into the provided pointer. If the Activity failed, +the failure is returned as an error. + +## Get a handle to an existing Standalone Activity {#get-activity-handle} + +Use `client.GetActivityHandle()` to create a handle to a previously started Standalone Activity. This is analogous to +`client.GetWorkflow()` for Workflow Executions. + +Both `ActivityID` and `RunID` are required. + +```go +handle := c.GetActivityHandle(client.GetActivityHandleOptions{ + ActivityID: "my-standalone-activity-id", + RunID: "the-run-id", +}) + +// Use the handle to get the result, describe, cancel, or terminate +var result string +err := handle.Get(context.Background(), &result) +if err != nil { + log.Fatalln("Unable to get activity result", err) +} +``` + +## List Standalone Activities {#list-activities} + +Use [`client.ListActivities()`](https://pkg.go.dev/go.temporal.io/sdk/client#Client) to list Standalone Activity +Executions that match a [List Filter](/list-filter) query. The result contains an iterator that yields +[`ActivityExecutionInfo`](https://pkg.go.dev/go.temporal.io/sdk/client#ActivityExecutionInfo) entries. + +```go +resp, err := c.ListActivities(context.Background(), client.ListActivitiesOptions{ + Query: "TaskQueue = 'standalone-activity-helloworld'", +}) +if err != nil { + log.Fatalln("Unable to list activities", err) +} + +for info, err := range resp.Results { + if err != nil { + log.Fatalln("Error iterating activities", err) + } + log.Printf("ActivityID: %s, Type: %s, Status: %v\n", + info.ActivityID, info.ActivityType, info.Status) +} +``` + +The `Query` field accepts the same [List Filter](/list-filter) syntax used for Workflow Visibility. For example, +`"ActivityType = 'Activity' AND Status = 'Running'"`. + +You can also list activities using the Temporal CLI: + +``` +temporal activity list +``` + +## Count Standalone Activities {#count-activities} + +Use [`client.CountActivities()`](https://pkg.go.dev/go.temporal.io/sdk/client#Client) to count Standalone Activity +Executions that match a [List Filter](/list-filter) query. + +```go +resp, err := c.CountActivities(context.Background(), client.CountActivitiesOptions{ + Query: "TaskQueue = 'standalone-activity-helloworld'", +}) +if err != nil { + log.Fatalln("Unable to count activities", err) +} + +log.Println("Total activities:", resp.Count) +``` + +## Run Standalone Activities with Temporal Cloud {#run-standalone-activities-temporal-cloud} + +This section assumes you are already familiar with +[how to connect a Worker to Temporal Cloud](https://docs.temporal.io/develop/go/core-application#run-a-temporal-cloud-worker). +The same [source code](https://github.com/temporalio/samples-go/tree/main/standalone-activity/helloworld) is used in +this section. The `tcld` CLI will be used to create a Namespace, and mTLS client certificates will be used to securely +connect the Worker to Temporal Cloud. + +### Install the latest `tcld` CLI and generate certificates + +To install the latest version of the `tcld` CLI, run the following command (on MacOS): + +``` +brew install temporalio/brew/tcld +``` + +If you don't already have certificates, you can generate them for mTLS Worker authentication using the command below: + +``` +tcld gen ca --org $YOUR_ORG_NAME --validity-period 1y --ca-cert ca.pem --ca-key ca.key +``` + +These certificates will be valid for one year. + +### Create your Namespace + +If you don't already have a Namespace, create one for your Standalone Activities: + +``` +tcld login + +tcld namespace create \ + --namespace \ + --cloud-provider aws \ + --region us-west-2 \ + --ca-certificate-file 'path/to/your/ca.pem' \ + --retention-days 1 +``` + +Alternatively, you can create a Namespace through the UI: +[https://cloud.temporal.io/namespaces](https://cloud.temporal.io/namespaces). + +### Run a Worker connected to Temporal Cloud with TLS certificates + +The sample uses [`envconfig.MustLoadDefaultClientOptions()`](https://pkg.go.dev/go.temporal.io/sdk/contrib/envconfig) to +read connection options from [environment variables](/references/client-environment-configuration). Set the following +environment variables before running the Worker: + +``` +export TEMPORAL_ADDRESS=.tmprl.cloud:7233 +export TEMPORAL_NAMESPACE= +export TEMPORAL_TLS_CLIENT_CERT_PATH='path/to/your/ca.pem' +export TEMPORAL_TLS_CLIENT_KEY_PATH='path/to/your/ca.key' +``` + +Then run the Worker: + +``` +go run standalone-activity/helloworld/worker/main.go +``` + +### Execute a Standalone Activity on Temporal Cloud + +In a separate terminal, set the same environment variables and run the starter: + +``` +export TEMPORAL_ADDRESS=.tmprl.cloud:7233 +export TEMPORAL_NAMESPACE= +export TEMPORAL_TLS_CLIENT_CERT_PATH='path/to/your/ca.pem' +export TEMPORAL_TLS_CLIENT_KEY_PATH='path/to/your/ca.key' + +go run standalone-activity/helloworld/starter/main.go +``` + +### Run a Worker connected to Temporal Cloud with API keys + +Alternatively, you can use an API key instead of TLS certificates: + +``` +export TEMPORAL_ADDRESS=..api.temporal.io:7233 +export TEMPORAL_NAMESPACE= +export TEMPORAL_API_KEY= +``` + +Then run the Worker and starter the same way: + +``` +go run standalone-activity/helloworld/worker/main.go +``` + +``` +go run standalone-activity/helloworld/starter/main.go +``` diff --git a/sidebars.js b/sidebars.js index 6a19646ab6..b38653fa0e 100644 --- a/sidebars.js +++ b/sidebars.js @@ -106,6 +106,7 @@ module.exports = { 'develop/go/message-passing', 'develop/go/cancellation', 'develop/go/asynchronous-activity-completion', + 'develop/go/standalone-activities', 'develop/go/versioning', 'develop/go/observability', 'develop/go/benign-exceptions', From 04fc64500c262621bda7b76455a68cd572aa966d Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Thu, 26 Feb 2026 21:07:30 -0500 Subject: [PATCH 7/8] Fix bugs --- docs/develop/python/standalone-activities.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/develop/python/standalone-activities.mdx b/docs/develop/python/standalone-activities.mdx index dec62d813a..5b6655a1eb 100644 --- a/docs/develop/python/standalone-activities.mdx +++ b/docs/develop/python/standalone-activities.mdx @@ -201,7 +201,7 @@ You can also use `client.get_activity_handle()` to create a handle to a previous ```python activity_handle = client.get_activity_handle( activity_id="my-standalone-activity-id", - activity_run_id="the-run-id", + run_id="the-run-id", ) ``` @@ -235,7 +235,7 @@ from temporalio.client import Client async def my_application(): client = await Client.connect("localhost:7233") - activities = await client.list_activities( + activities = client.list_activities( query="TaskQueue = 'my-task-queue'", ) From e5fe1fbfe25fabdd68841d058f3d35cd7a58b157 Mon Sep 17 00:00:00 2001 From: Dan Davison Date: Fri, 27 Feb 2026 08:27:17 -0500 Subject: [PATCH 8/8] Link to job queue, edits --- .../activities/standalone-activity.mdx | 16 ++++++++++------ .../job-queue.mdx | 4 ++-- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/docs/encyclopedia/activities/standalone-activity.mdx b/docs/encyclopedia/activities/standalone-activity.mdx index 880b96f06f..f17e0634fc 100644 --- a/docs/encyclopedia/activities/standalone-activity.mdx +++ b/docs/encyclopedia/activities/standalone-activity.mdx @@ -26,13 +26,17 @@ See [limitations](#pre-release-limitations) below. ## What is a Standalone Activity? {#standalone-activity} -A top-level [Activity Execution](/activity-execution) that is started directly by a [Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a Standalone Activity. +A top-level [Activity Execution](/activity-execution) that is started directly by a +[Client](/encyclopedia/temporal-sdks#temporal-client), without using a Workflow, is called a +Standalone Activity. -If you need to orchestrate multiple Activity Executions, then you should use a Workflow. But if you -just need to execute a single Activity, then you can use a Standalone Activity. This will result in -fewer [Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud than using a Workflow to run a single Activity. If your Activity -Execution is short-lived, then you will also notice lower latency, since there are fewer worker -round-trips than when executing the Activity in a Workflow. +Standalone Activities are Temporal's [job queue](/evaluate/development-production-features/job-queue). + +If you need to orchestrate multiple Activities, then you should use a Workflow. But if you just need +to execute a single Activity, then you can use a Standalone Activity. This will result in fewer +[Billable Actions](/cloud/actions#actions-in-workflows) in Temporal Cloud than using a Workflow to +run a single Activity. If your Activity Execution is short-lived, then you will also notice lower +latency, since there are fewer worker round-trips than when executing the Activity in a Workflow. Standalone Activities support the same retry policies and timeouts as Workflow Activities, and you write your Activity Functions in the same way for both. In fact, an Activity Function can be diff --git a/docs/evaluate/development-production-features/job-queue.mdx b/docs/evaluate/development-production-features/job-queue.mdx index b1c9b6a086..549e87a1a9 100644 --- a/docs/evaluate/development-production-features/job-queue.mdx +++ b/docs/evaluate/development-production-features/job-queue.mdx @@ -28,7 +28,7 @@ They let you use Temporal Activities as background jobs, in addition to using th Temporal provides stronger guarantees, better visibility, and more control than traditional job queues - while remaining cost-effective for high-volume use cases and offering a clean upgrade path to multi-step workflow orchestration. -### Overview +### Overview Standalone Activities add the ability to execute any Temporal Activity as a top-level Activity Execution for durable job processing. @@ -42,7 +42,7 @@ Standalone Activities add the ability to execute any Temporal Activity as a top- - Jobs are submitted as Standalone Activity Executions - Each job is durably persisted with Temporal reliability, so jobs are not lost -- Jobs are scheduled with priority, fairness, deduplication and no head of line blocking +- Jobs are scheduled with priority, fairness, deduplication and no head-of-line blocking - Workers poll task queues and execute Activities (you run your own Workers) - Temporal ensures retries, timeouts, and exponential backoff policy is enforced