Skip to content

Commit 452e44e

Browse files
authored
Merge pull request #313162 from torosent/add-large-payload
Add Durable Task Scheduler large payload docs
2 parents 03548f0 + 7151b73 commit 452e44e

5 files changed

Lines changed: 322 additions & 1 deletion

File tree

articles/azure-functions/durable/TOC.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@
145145
items:
146146
- name: Author Durable Functions apps using the PowerShell SDK
147147
href: durable-functions-powershell-v2-sdk-migration-guide.md
148+
- name: Large payload support - Durable Task Scheduler
149+
href: ./durable-task-scheduler/durable-task-scheduler-large-payloads.md?pivots=durable-functions
148150
- name: Deploy
149151
items:
150152
- name: Continuous deployment
@@ -241,6 +243,8 @@
241243
href: ./durable-task-scheduler/durable-task-schedulers-schedules.md
242244
- name: Diagnostics
243245
href: durable-task-diagnostics.md
246+
- name: Large payload support
247+
href: ./durable-task-scheduler/durable-task-scheduler-large-payloads.md?pivots=durable-task-sdks
244248
- name: OpenTelemetry and distributed tracing
245249
href: ./durable-task-scheduler/durable-task-scheduler-opentelemetry-tracing.md?pivots=durable-task-sdks
246250
- name: Troubleshooting guide
@@ -277,6 +281,8 @@
277281
href: ./durable-task-scheduler/durable-task-schedulers-schedules.md
278282
- name: OpenTelemetry and distributed tracing
279283
href: ./durable-task-scheduler/durable-task-scheduler-opentelemetry-tracing.md
284+
- name: Large payload support
285+
href: ./durable-task-scheduler/durable-task-scheduler-large-payloads.md
280286
- name: Throughput benchmarks
281287
href: ./durable-task-scheduler/durable-task-scheduler-work-item-throughput.md
282288
- name: Billing

articles/azure-functions/durable/choose-orchestration-framework.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,6 @@ Get started with the framework you chose:
151151
> [Durable Functions overview](durable-functions-overview.md)
152152
153153
> [!div class="nextstepaction"]
154-
> [Durable Functions overview](./durable-task-scheduler/durable-task-overview.md)
154+
> [Durable Task SDKs overview](./durable-task-scheduler/durable-task-overview.md)
155155
156156
Then, learn more about the [Durable Task Scheduler backend provider](durable-task-scheduler/durable-task-scheduler.md).

articles/azure-functions/durable/durable-functions-serialization-and-persistence.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ To mitigate the impact of large inputs and outputs, you can:
5050
- Delegate work to sub-orchestrators to load balance the history memory burden across multiple orchestrators, keeping the memory footprint of individual histories small.
5151
- Store large data in external storage (such as Azure Blob Storage) and pass lightweight identifiers that allow you to retrieve that data inside activity functions when needed.
5252

53+
If you use Durable Task Scheduler, you can also use [large payload support](./durable-task-scheduler/durable-task-scheduler-large-payloads.md) to offload larger payloads to Azure Blob Storage.
54+
5355
> [!TIP]
5456
> The best practice for dealing with large data is to keep it in external storage and materialize that data only inside activities, when needed.
5557
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
---
2+
title: Large payload support with Durable Task Scheduler (Preview)
3+
description: Learn how to use preview large payload support in Durable Functions and the Durable Task SDKs with Durable Task Scheduler and Azure Blob Storage.
4+
ms.topic: conceptual
5+
ms.date: 03/14/2026
6+
ms.author: torosent
7+
ms.service: azure-functions
8+
ms.subservice: durable-task-scheduler
9+
ms.devlang: csharp
10+
zone_pivot_groups: azure-durable-approach
11+
---
12+
13+
# Large payload support with Durable Task Scheduler (Preview)
14+
15+
Large payload support lets your app pass orchestration inputs and activity outputs that exceed the [Durable Task Scheduler](durable-task-scheduler.md) message size limit. When a payload goes over the configured threshold, the framework stores the serialized payload in Azure Blob Storage and sends a small reference through Durable Task Scheduler.
16+
17+
This feature is available only for C# apps:
18+
19+
- [Durable Functions](../durable-functions-overview.md) with the .NET isolated worker
20+
- [.NET Durable Task SDK](durable-task-overview.md)
21+
22+
If your workflow stores data in Blob Storage and passes only a URI or identifier, keep using that pattern. Use large payload support when your orchestration logic must pass the payload between durable operations. For general guidance, see [Data persistence and serialization in Durable Functions](../durable-functions-serialization-and-persistence.md#keep-inputs-and-outputs-small).
23+
24+
## Supported frameworks
25+
26+
This table shows large payload support by framework.
27+
28+
| Framework | Support status | What you need |
29+
| --- | --- | --- |
30+
| Durable Functions | Supported in .NET isolated C# | Use Durable Task Scheduler as the storage provider and use `AzureWebJobsStorage` for payload blobs |
31+
| Durable Task SDKs | Supported in .NET | Use `Microsoft.DurableTask.Extensions.AzureBlobPayloads` with Azure Blob Storage |
32+
| JavaScript, Python, PowerShell, and Java | Not available | Use external storage and pass references between durable operations |
33+
34+
## How it works
35+
36+
When you enable large payload support, the runtime follows the same high level flow in both hosting models:
37+
38+
1. It serializes the orchestration input or activity output.
39+
1. If the payload size exceeds your configured threshold, the runtime compresses the payload with gzip.
40+
1. It writes the compressed payload to Azure Blob Storage.
41+
1. It sends a blob reference through Durable Task Scheduler instead of the full payload.
42+
1. The runtime automatically resolves the reference before your orchestrator or activity code reads the value.
43+
44+
The current .NET samples use deterministic, low-compressibility 1.5 MiB payloads. That keeps the stored blob size representative, even though the runtime writes blobs with gzip content encoding.
45+
46+
Large payload support changes how payloads move through the runtime. It doesn't change the recommendation to keep durable state as small as practical.
47+
48+
## Choose the right pattern
49+
50+
Use the simplest pattern for your scenario.
51+
52+
| Use this pattern | When to use it |
53+
| --- | --- |
54+
| Large payload support | Your orchestration passes the payload between durable operations, and the payload exceeds the scheduler message limit |
55+
| External storage plus references | Your activities load data directly from storage, and you want the smallest possible orchestration state |
56+
57+
## Enable large payload support
58+
59+
::: zone pivot="durable-functions"
60+
61+
Large payload support in Durable Functions is available only for .NET isolated C# apps that use Durable Task Scheduler as the storage provider.
62+
63+
# [C#](#tab/csharp)
64+
65+
Before you enable the feature, make sure your app:
66+
67+
- Uses the .NET isolated worker.
68+
- References `Microsoft.Azure.Functions.Worker.Extensions.DurableTask` and `Microsoft.Azure.Functions.Worker.Extensions.DurableTask.AzureManaged`.
69+
- Sets `AzureWebJobsStorage` to the storage account that holds externalized payloads.
70+
- Sets `DTS_CONNECTION_STRING` and `TASKHUB_NAME` for the target scheduler and task hub.
71+
72+
Then enable large payload storage in [host.json](../durable-functions-bindings.md#host-json):
73+
74+
```json
75+
{
76+
"version": "2.0",
77+
"extensions": {
78+
"durableTask": {
79+
"storageProvider": {
80+
"type": "azureManaged",
81+
"connectionStringName": "DTS_CONNECTION_STRING",
82+
"largePayloadStorageEnabled": true,
83+
"largePayloadStorageThresholdBytes": 900000
84+
},
85+
"hubName": "%TASKHUB_NAME%"
86+
}
87+
}
88+
}
89+
```
90+
91+
Set `largePayloadStorageThresholdBytes` below the Durable Task Scheduler message size boundary so the runtime externalizes payloads before they approach the limit.
92+
93+
Use the standard Durable Functions APIs in your orchestrator and activity code. The runtime automatically resolves blob references before `context.GetInput<T>()` and `context.CallActivityAsync<T>()` return data.
94+
95+
By default, the extension writes externalized payloads to the `durabletask-payloads` container in the storage account configured by `AzureWebJobsStorage`.
96+
97+
For end-to-end examples, see these samples:
98+
99+
- [Durable Functions large payload sample](https://github.com/Azure-Samples/Durable-Task-Scheduler/tree/main/samples/durable-functions/dotnet/LargePayload)
100+
- [Durable Functions large payload fan-out/fan-in sample](https://github.com/Azure-Samples/Durable-Task-Scheduler/tree/main/samples/durable-functions/dotnet/LargePayloadFanOutFanIn)
101+
102+
# [JavaScript](#tab/javascript)
103+
104+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
105+
106+
# [Python](#tab/python)
107+
108+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
109+
110+
# [PowerShell](#tab/powershell)
111+
112+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
113+
114+
# [Java](#tab/java)
115+
116+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
117+
118+
---
119+
120+
::: zone-end
121+
122+
::: zone pivot="durable-task-sdks"
123+
124+
Large payload support in the Durable Task SDKs is available only for .NET apps.
125+
126+
# [C#](#tab/csharp)
127+
128+
Install the Azure Blob payload extension package:
129+
130+
```bash
131+
dotnet add package Microsoft.DurableTask.Extensions.AzureBlobPayloads
132+
```
133+
134+
Install the Azure Managed client and worker packages for Durable Task Scheduler:
135+
136+
```bash
137+
dotnet add package Microsoft.DurableTask.Client.AzureManaged
138+
dotnet add package Microsoft.DurableTask.Worker.AzureManaged
139+
```
140+
141+
Register an externalized payload store, choose a threshold, and enable payload resolution on both the client and the worker:
142+
143+
```csharp
144+
builder.Services.AddExternalizedPayloadStore(options =>
145+
{
146+
options.ExternalizeThresholdBytes = 900_000;
147+
options.ConnectionString = builder.Configuration["PAYLOAD_STORAGE_CONNECTION_STRING"]
148+
?? "UseDevelopmentStorage=true";
149+
options.ContainerName = "durabletask-payloads";
150+
});
151+
152+
builder.Services.AddDurableTaskClient(client =>
153+
{
154+
client.UseDurableTaskScheduler(schedulerConnectionString);
155+
client.UseExternalizedPayloads();
156+
});
157+
158+
builder.Services.AddDurableTaskWorker(worker =>
159+
{
160+
worker.UseDurableTaskScheduler(schedulerConnectionString);
161+
worker.UseExternalizedPayloads();
162+
});
163+
```
164+
165+
If you use Microsoft Entra ID instead of a storage connection string, set `options.AccountUri` and `options.Credential`. The sample uses `DefaultAzureCredential` and can optionally target a user-assigned managed identity.
166+
167+
Keep `ExternalizeThresholdBytes` at or below `1,048,576` bytes. The sample uses `900,000` bytes so payloads are offloaded before they approach the 1 MiB scheduler message boundary.
168+
169+
For an end-to-end .NET example, see the [Durable Task SDK large payload sample](https://github.com/Azure-Samples/Durable-Task-Scheduler/tree/main/samples/durable-task-sdks/dotnet/LargePayload).
170+
171+
# [JavaScript](#tab/javascript)
172+
173+
Large payload support with Durable Task Scheduler is available only for the .NET Durable Task SDK.
174+
175+
# [PowerShell](#tab/powershell)
176+
177+
Large payload support with Durable Task Scheduler is available only for the .NET Durable Task SDK.
178+
179+
# [Python](#tab/python)
180+
181+
Large payload support with Durable Task Scheduler is available only for the .NET Durable Task SDK.
182+
183+
# [Java](#tab/java)
184+
185+
Large payload support with Durable Task Scheduler is available only for the .NET Durable Task SDK.
186+
187+
---
188+
189+
::: zone-end
190+
191+
## Environment variable configuration
192+
193+
::: zone pivot="durable-functions"
194+
195+
Use these local settings or app settings with the current Durable Functions samples.
196+
197+
# [C#](#tab/csharp)
198+
199+
| Setting | Description | Sample default |
200+
| --- | --- | --- |
201+
| `FUNCTIONS_WORKER_RUNTIME` | Azure Functions isolated worker runtime | `dotnet-isolated` |
202+
| `AzureWebJobsStorage` | Storage for Functions host state and payload blobs | `UseDevelopmentStorage=true` locally |
203+
| `DTS_CONNECTION_STRING` | Durable Task Scheduler connection string | `Endpoint=http://localhost:8080;Authentication=None` |
204+
| `TASKHUB_NAME` | Target task hub | `default` |
205+
| `PAYLOAD_SIZE_BYTES` | Payload size used by the starter or generated by each activity | `1572864` |
206+
| `ACTIVITY_COUNT` | Number of parallel activities in the fan-out/fan-in sample only | `3` |
207+
208+
The `ACTIVITY_COUNT` setting is used only by the `LargePayloadFanOutFanIn` sample. The `LargePayload` round-trip sample doesn't read it.
209+
210+
# [JavaScript](#tab/javascript)
211+
212+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
213+
214+
# [Python](#tab/python)
215+
216+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
217+
218+
# [PowerShell](#tab/powershell)
219+
220+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
221+
222+
# [Java](#tab/java)
223+
224+
Large payload support with Durable Task Scheduler is available only for .NET isolated C# Durable Functions apps.
225+
226+
---
227+
228+
::: zone-end
229+
230+
::: zone pivot="durable-task-sdks"
231+
232+
Use these environment variables with the current .NET Durable Task SDK sample.
233+
234+
# [C#](#tab/csharp)
235+
236+
| Variable | Description | Sample default |
237+
| --- | --- | --- |
238+
| `DURABLE_TASK_SCHEDULER_CONNECTION_STRING` | Durable Task Scheduler connection string | `Endpoint=http://localhost:8080;TaskHub=default;Authentication=None` |
239+
| `PAYLOAD_STORAGE_CONNECTION_STRING` | Blob storage connection string for externalized payloads | `UseDevelopmentStorage=true` |
240+
| `PAYLOAD_STORAGE_ACCOUNT_URI` | Blob account URI for identity-based payload storage access | unset |
241+
| `PAYLOAD_CONTAINER_NAME` | Blob container for externalized payloads | `durabletask-payloads` |
242+
| `PAYLOAD_SIZE_BYTES` | Default payload size used by the run endpoint | `1572864` |
243+
| `EXTERNALIZE_THRESHOLD_BYTES` | Blob offload threshold | `900000` |
244+
| `PAYLOAD_STORAGE_MANAGED_IDENTITY_CLIENT_ID` | Optional user-assigned managed identity client ID for storage access | unset |
245+
| `AZURE_CLIENT_ID` | Alternate way to select a user-assigned managed identity | unset |
246+
| `ASPNETCORE_URLS` | Listen URLs for the sample's HTTP host | framework default |
247+
248+
If `PAYLOAD_STORAGE_CONNECTION_STRING` isn't set and `PAYLOAD_STORAGE_ACCOUNT_URI` is provided, the sample uses `DefaultAzureCredential`. If you need a specific user-assigned identity, set `PAYLOAD_STORAGE_MANAGED_IDENTITY_CLIENT_ID` or `AZURE_CLIENT_ID`.
249+
250+
# [JavaScript](#tab/javascript)
251+
252+
This sample is shown for .NET, Java, and Python.
253+
254+
# [PowerShell](#tab/powershell)
255+
256+
This sample is shown for .NET, Java, and Python.
257+
258+
# [Python](#tab/python)
259+
260+
This sample is shown for .NET, Java, and Python.
261+
262+
# [Java](#tab/java)
263+
264+
This sample is shown for .NET, Java, and Python.
265+
266+
---
267+
268+
::: zone-end
269+
270+
## Azure permissions
271+
272+
When you use Azure resources instead of local emulators, the app identity needs access to Durable Task Scheduler and Blob Storage:
273+
274+
- Grant `Durable Task Data Contributor` on the app's task hub.
275+
- Grant `Storage Blob Data Contributor` on the storage account that stores payload blobs.
276+
277+
These permissions apply to Durable Functions apps and Durable Task SDK apps that use a managed identity.
278+
279+
## Check that payload offload works
280+
281+
After you enable payload offload, run an orchestration with an input or output larger than your configured threshold. Then check for both signals:
282+
283+
- The orchestration completes successfully even though the payload exceeds 1 MiB.
284+
- Blob entries appear in the `durabletask-payloads` container.
285+
286+
For local development, run this Azure CLI command to inspect the container:
287+
288+
```azurecli
289+
az storage blob list \
290+
--connection-string "UseDevelopmentStorage=true" \
291+
--container-name durabletask-payloads \
292+
--output table
293+
```
294+
295+
The sample apps also validate the round trip:
296+
297+
- The Durable Functions samples return a small summary object that confirms the input and output sizes.
298+
- The .NET Durable Task SDK sample prints whether the run creates new payload blobs.
299+
300+
Because the runtime stores externalized payloads with gzip content encoding, Azure reports the compressed on-disk blob size. With the current low-compressibility sample payloads, those blob sizes should stay reasonably close to the logical payload size.
301+
302+
> [!NOTE]
303+
> Purging orchestration instances doesn't currently delete the corresponding externalized payload blobs from Azure Blob Storage. If you need to remove those payloads, delete the blobs from the storage account separately.
304+
305+
## Next steps
306+
307+
> [!div class="nextstepaction"]
308+
> [Configure Durable Functions with Durable Task Scheduler](quickstart-durable-task-scheduler.md)
309+
310+
> [!div class="nextstepaction"]
311+
> [Create an app with the Durable Task SDKs](quickstart-portable-durable-task-sdks.md)

articles/azure-functions/durable/durable-task-scheduler/durable-task-scheduler.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ Stale orchestration data should be purged periodically to ensure efficient stora
165165
| Orchestration custom status | 1 MB |
166166
| Entity state | 1 MB |
167167

168+
If you need to pass larger payloads, use [large payload support with Durable Task Scheduler](./durable-task-scheduler-large-payloads.md). That option is currently available only for C# apps in Durable Functions .NET isolated and the .NET Durable Task SDK.
169+
168170
- **Orchestration instance ID length:**
169171

170172
Orchestration instance IDs are limited to a maximum length of 100 characters.

0 commit comments

Comments
 (0)