|
2 | 2 | id: local-activity |
3 | 3 | title: Local Activity |
4 | 4 | sidebar_label: Local Activity |
5 | | -description: Learn about Local Activities in Temporal, their benefits, execution model, and when to use them. |
| 5 | +description: Learn about Local Activities in Temporal, how they work, when to use them, and how they differ from regular Activities. |
6 | 6 | slug: /local-activity |
7 | 7 | toc_max_heading_level: 4 |
8 | 8 | keywords: |
9 | 9 | - explanation |
10 | 10 | - term |
11 | 11 | - timeouts |
| 12 | + - activities |
| 13 | + - local activities |
| 14 | + - workflow |
12 | 15 | tags: |
13 | 16 | - Concepts |
14 | 17 | - Activities |
15 | 18 | - Durable Execution |
16 | 19 | --- |
17 | 20 |
|
18 | | -This page discusses [Local Activity](#local-activity). |
19 | | - |
20 | 21 | ## What is a Local Activity? {/* #local-activity */} |
21 | 22 |
|
22 | | -A Local Activity is an [Activity Execution](/activity-execution) that executes in the same process as the [Workflow Execution](/workflow-execution) that spawns it. |
| 23 | +A Local Activity is an [Activity Execution](/activity-execution) that executes in the same Worker process as the [Workflow Execution](/workflow-execution) that schedules it. |
| 24 | + |
| 25 | +Unlike a regular Activity, a Local Activity never enters an Activity Task Queue. Instead, the Workflow Worker executes it directly in an in-process queue. Because it avoids the round trip through the Temporal Service, a Local Activity has significantly lower latency and produces fewer Event History entries than a regular Activity. |
| 26 | + |
| 27 | +Local Activities help with performance optimization and are not a replacement for regular Activities. |
| 28 | + |
| 29 | +Consider using a Local Activity only when the operation: |
| 30 | + |
| 31 | +- is short-lived (completes in a few seconds), including retries |
| 32 | +- can execute in the same binary as the Workflow |
| 33 | +- does not require routing to a specific Worker or Task Queue |
| 34 | +- does not require global rate limiting |
| 35 | +- [is idempotent](/develop/python/best-practices/error-handling#make-activities-idempotent) |
| 36 | + |
| 37 | +For most production workloads, regular Activities remain the recommended default. |
| 38 | + |
| 39 | +:::tip Recommendation |
| 40 | + |
| 41 | +Use Local Activities only when your use case requires the performance optimization they provide, such as high-throughput Workflows with many very short-lived operations. For most business logic, regular Activities are the better choice. |
| 42 | + |
| 43 | +::: |
| 44 | + |
| 45 | +## How Local Activities execute |
| 46 | + |
| 47 | +Regular Activities are coordinated through the Temporal Service. |
| 48 | + |
| 49 | +The execution flow is: |
| 50 | + |
| 51 | +1. A Workflow schedules an Activity. |
| 52 | +2. The Workflow completes its Workflow Task by sending a `ScheduleActivityTask` command to the Temporal Service. |
| 53 | +3. The Temporal Service creates an Activity Task. |
| 54 | +4. An Activity Worker polls the Activity Task Queue and executes the Activity. |
| 55 | +5. The Activity result is recorded in Event history. |
| 56 | +6. The Workflow resumes in a new Workflow Task. |
| 57 | + |
| 58 | +Local Activities follow a shorter execution path: |
| 59 | + |
| 60 | +1. A Workflow schedules a Local Activity. |
| 61 | +2. The Local Activity is placed into an in-process queue within the Workflow Worker. |
| 62 | +3. The Workflow Worker executes the Local Activity immediately. |
| 63 | +4. The result is returned directly to the Workflow. |
| 64 | +5. When the Workflow Task completes, the Worker records a `MarkerRecorded` event containing the Local Activity result. |
| 65 | + |
| 66 | +Unlike regular Activities, scheduling and execution occur entirely within the Worker process. Only the final marker is persisted to Event history. |
| 67 | + |
| 68 | +## Workflow Task heartbeating |
| 69 | + |
| 70 | +Local Activities do **not** support Activity heartbeats. Instead, the SDK supports Workflow Task heartbeating. |
| 71 | + |
| 72 | +Workflow Task heartbeating means that if a Local Activity approaches approximately 80% of the Workflow Task Timeout (10 seconds by default), the Worker completes the current Workflow Task and requests a new one from the Temporal Service. This renews the Worker's authorization to continue executing the Workflow and allows the Local Activity to keep running without exceeding the Workflow Task Timeout. |
| 73 | + |
| 74 | +This enables Local Activities to run longer than a single Workflow Task timeout, but it comes with tradeoffs: |
| 75 | + |
| 76 | +- Each Workflow Task heartbeat adds additional Events to the Event history. |
| 77 | +- Signals and other external Workflow events are not processed until the Local Activities finish. |
| 78 | +- Commands generated by the Workflow are not sent to the Temporal Service until one of the following occurs: |
| 79 | + - the Local Activity completes |
| 80 | + - the next Workflow Task heartbeat occurs |
| 81 | + |
| 82 | +If your operation regularly approaches the Workflow Task timeout, it is usually better implemented as a regular Activity. |
| 83 | + |
| 84 | +You can monitor your Local Activities by using the [`local_activity_total` metric](/references/sdk-metrics#local_activity_total) to determine how many Local Activity Executions have been made. You can also check your Event History for `RecordMarker` entries. |
| 85 | + |
| 86 | +## Failure and durability |
| 87 | + |
| 88 | +Regular Activities are durably tracked by the Temporal Service. Scheduling, completion, retries, and failures are all recorded in the Event history. If a Worker crashes after an Activity completes, the completed Activity is not executed again. |
| 89 | + |
| 90 | +Local Activities behave differently. A Local Activity result becomes durable only when the enclosing Workflow Task successfully completes and records a `MarkerRecorded` event. Until then, execution exists only in Worker memory. |
| 91 | + |
| 92 | +If the Worker crashes before the Workflow Task completes, the Workflow Task is retried, causing Local Activities executed during that Workflow Task to run again. |
| 93 | + |
| 94 | +Because of this behavior, Local Activities provide at-least-once execution semantics and should always be idempotent. You can learn more about the behavior at shutdown in the [Workers section on Local Activities](encyclopedia/workers/worker-shutdown#local-activities). |
| 95 | + |
| 96 | +Once a `MarkerRecorded` event has been written to the Event history, replay uses the recorded result rather than executing the Local Activity again. |
| 97 | + |
| 98 | +## Mixing Local Activities and regular Activities |
| 99 | + |
| 100 | +A Workflow can freely combine Local Activities and regular Activities. |
| 101 | + |
| 102 | +For example: |
| 103 | + |
| 104 | +```mermaid |
| 105 | +flowchart LR |
| 106 | + LA[Local Activity A] --> LB[Local Activity B] --> RC[Regular Activity C] |
| 107 | +``` |
| 108 | + |
| 109 | +When the Workflow Task completes after scheduling Activity C, the Worker sends commands similar to: |
| 110 | + |
| 111 | +- `MarkerRecorded` (Local Activity A) |
| 112 | +- `MarkerRecorded` (Local Activity B) |
| 113 | +- `ScheduleActivityTask` (Activity C) |
| 114 | + |
| 115 | +If Activity C later fails or retries, the Workflow replays using the recorded markers for A and B. Those completed Local Activities are not executed again because their results have already been persisted in the Event history. Only Activity C is retried according to its Retry Policy. |
| 116 | + |
| 117 | +The only time completed Local Activities execute again is if the Worker fails before their completion markers are recorded. Long retry intervals are inefficient because retries eventually require Workflow Timers and additional Event history entries. |
| 118 | + |
| 119 | +## Choosing between regular Activities and Local Activities |
| 120 | + |
| 121 | +Choose a regular Activity unless you have a specific need for the performance optimization that Local Activities provide. |
| 122 | + |
| 123 | +Use a Local Activity when: |
| 124 | + |
| 125 | +- execution completes in a few seconds |
| 126 | +- retries are expected to be short |
| 127 | +- the operation is idempotent |
| 128 | +- low latency is more important than full durability |
| 129 | +- routing, rate limiting, and separate Activity Workers are unnecessary |
| 130 | + |
| 131 | +Use a regular Activity when: |
| 132 | + |
| 133 | +- interacting with external systems |
| 134 | +- execution may take longer than a few seconds |
| 135 | +- retries may span minutes or hours |
| 136 | +- Activity heartbeating is required |
| 137 | +- strong durability guarantees are important |
| 138 | + |
| 139 | +Regular Activities are the right choice for most applications. Local Activities are an optimization for specialized, high-throughput workloads where minimizing latency and Event history size outweighs their reduced durability guarantees. |
23 | 140 |
|
24 | | -Some Activity Executions are very short-living and do not need the queuing semantic, flow control, rate limiting, and routing capabilities. |
25 | | -For this case, Temporal supports the Local Activity feature. |
| 141 | +### Use cases for Local Activities |
26 | 142 |
|
27 | | -The main benefit of Local Activities is that they use less Temporal Service resources (for example, fewer History events) and have much lower latency overhead (because no need to roundtrip to the Temporal Service) compared to normal Activity Executions. |
28 | | -However, Local Activities are subject to shorter durations and a lack of rate limiting. |
| 143 | +Good use cases for Local Activities include: |
29 | 144 |
|
30 | | -Consider using Local Activities for functions that are the following: |
| 145 | +- Lightweight data transformations |
| 146 | +- Small computations |
| 147 | +- Reading from an in-memory cache |
| 148 | +- Fast local filesystem operations |
| 149 | +- High-throughput Workflows with many very short-lived operations |
31 | 150 |
|
32 | | -- can be implemented in the same binary as the Workflow that calls them. |
33 | | -- do not require global rate limiting. |
34 | | -- do not require routing to a specific Worker or Worker pool. |
35 | | -- no longer than a few seconds, inclusive of retries. |
| 151 | +Use regular Activities for: |
36 | 152 |
|
37 | | -If it takes longer than 80% of the Workflow Task Timeout (which is 10 seconds by default), the Worker will ask the Temporal Service to create a new Workflow Task to extend the "lease" for processing the Local Activity. |
38 | | -The Worker will continue doing so until the Local Activity has completed. |
39 | | -This is called Workflow Task Heartbeating. |
40 | | -The drawbacks of long-running Local Activities are: |
| 153 | +- Network requests |
| 154 | +- Database operations |
| 155 | +- External API calls |
| 156 | +- Long-running work |
| 157 | +- Operations requiring durable retries |
| 158 | +- Operations that benefit from Task Queue routing or rate limiting |
41 | 159 |
|
42 | | -- Each new Workflow Task results in 3 more Events in History. |
43 | | -- The Workflow won't get notified of new events like Signals and completions until the next Workflow Task Heartbeat. |
44 | | -- New Commands created by the Workflow concurrently with the Local Activity will not be sent to the Temporal Service until either the Local Activity completes or the next Workflow Task Heartbeat. |
| 160 | +### Activity vs. Local Activity |
45 | 161 |
|
46 | | -Using a Local Activity without understanding its limitations can cause various production issues. |
47 | | -**We recommend using regular Activities unless your use case requires very high throughput and large Activity fan outs of very short-lived Activities.** |
48 | | -More guidance in choosing between [Local Activity vs Activity](https://community.temporal.io/t/local-activity-vs-activity/290/3) is available in our forums. |
| 162 | +| Feature | Activity | Local Activity | |
| 163 | +| --- | --- | --- | |
| 164 | +| Execution | Activity Worker | Workflow Worker | |
| 165 | +| Task Queue | Yes | No | |
| 166 | +| Service round trip | Required | Not required | |
| 167 | +| Latency | Higher | Lower | |
| 168 | +| Event history | Fully recorded | `MarkerRecorded` on completion | |
| 169 | +| Heartbeating | Activity heartbeats | Workflow Task heartbeating | |
| 170 | +| Retry durability | Durable | At-least-once until marker is recorded | |
| 171 | +| Signal responsiveness | Unaffected | Delayed while the Workflow Task executes | |
| 172 | +| Best for | General-purpose work | Short, high-throughput operations | |
0 commit comments