This release is a pre-release and may not be stable for production use.
Azure Functions Durable (Python) — 2.x
azure-functions-durable is the Python SDK provider for
Durable Azure Functions,
built on top of the durabletask SDK.
Requirements
- Python 3.13+
- The decorator-based Azure Functions programming model (
DFApp/Blueprint)
Installation
pip install azure-functions-durable
Overview
Author orchestrations, activities, and entities as Azure Functions and let the
Durable Task runtime handle scheduling, checkpointing, and replay. Both
durabletask-native two-argument functions (def orchestrator(ctx, input)) and
v1-style single-argument functions (def orchestrator(context)) are supported,
along with class-based entities and a compatibility layer over the v1 API.
Key capabilities include durable orchestrations and sub-orchestrations, durable
timers, external events, durable entities, retries, versioning, durable HTTP
calls (context.call_http(...)), recurring scheduled tasks, and history export.
Large payloads
Configure a durabletask.payload.PayloadStore once at app startup to store large
serialized payloads outside orchestration history. For Azure Blob Storage, install
the optional dependencies:
pip install azure-functions-durable "durabletask[azure-blob-payloads]" aiohttp
In your Function app, configure the root DFApp before any invocations:
import os
import azure.durable_functions as df
from durabletask.extensions.azure_blob_payloads import (
BlobPayloadStore,
BlobPayloadStoreOptions,
)
app = df.DFApp()
app.configure_large_payloads(
payload_store=BlobPayloadStore(BlobPayloadStoreOptions(
connection_string=os.environ["PAYLOAD_STORAGE_CONNECTION_STRING"],
container_name="durable-payloads",
threshold_bytes=256 * 1024,
))
)
Set PAYLOAD_STORAGE_CONNECTION_STRING in your Function app settings (or in
local.settings.json for local development). The store automatically uploads
serialized payloads above the threshold and downloads their contents when the
SDK consumes them. Orchestration and activity inputs and outputs, custom status,
external events, and entity inputs, results, and state use the configured store.
Sub-orchestrations and continue-as-new use it as well. The default maximum stored
payload size is 10 MiB; max_stored_payload_bytes can configure this limit.
Configuration applies to both synchronous and asynchronous durable clients and
all registered blueprints, including blueprints imported before configuration.
There is one store per Python worker process. Registering the same store object
again is allowed; registering a different object raises ValueError. Configure
every scaled-out worker with access to the same backing storage and retain that
access across deployments. Keep the store open for the process lifetime.
This is SDK-managed storage, separate from the Azure Storage backend's automatic large-message handling. Without configuration, the SDK keeps payloads inline. Use the configured Python clients to retrieve hydrated payloads. Host management HTTP endpoints and other consumers that do not use this configuration can expose reference strings instead. Applications exchanging externalized payloads must agree on the store and reference encoding; Functions references are JSON strings.
Registered orchestration and entity handlers await the store's async methods before and after execution. Orchestrators remain synchronous generators, and orchestration replay and entity code run on execution threads with their invocation logging context preserved. Their payload downloads and uploads do not occupy those threads, and serialization does not access storage during replay. Custom stores must implement genuinely nonblocking async methods to benefit from this behavior.
For orchestration and entity execution, the SDK reuses the Functions runtime's
thread pool when the runtime exposes it; otherwise it uses a process-wide SDK
pool. Both honor PYTHON_THREADPOOL_THREAD_COUNT.
Activities retain their synchronous or asynchronous calling convention.
Synchronous activities use synchronous storage inside the host-managed execution
thread and remain directly callable without await; async activities await
async storage. Direct calls to decorated activities return ordinary Python values
without accessing payload storage; transport processing applies only to host
binding invocations. Binding converters perform no storage I/O. Synchronous functions
still receive the synchronous durable client, and synchronous client APIs use
synchronous storage. Direct Orchestrator.handle() and Orchestrator.create()
adapters also remain synchronous.
Both client history APIs hydrate entity operation inputs and results, including values nested in the host's entity protocol envelopes. During orchestration replay, nested entity results are hydrated, but historical nested request inputs are not downloaded because replay only needs their correlation metadata. Historical scheduled activity inputs are also not downloaded during replay; explicit history retrieval continues to hydrate those inputs.
To pass a reference as application data for later retrieval, wrap it in an
object, for example {"reference": "blob:v1:container:blob"}. Reference detection
does not recursively inspect strings inside application JSON objects. The
wrapper preserves the literal reference whether the object stays inline or is
itself externalized. Keep the wrapper whenever passing that value across a
durable payload boundary; passing its string field alone opts back into reference
interpretation. Custom payload stores define their own reserved token syntax.
Unit testing entities
Use execute_entity() to run one entity operation in-process without a
Functions host or Durable Task backend. It supports v1-style entity functions,
durabletask-native entity functions, and DurableEntity subclasses:
from azure.durable_functions.testing import execute_entity
from durabletask.entities import DurableEntity
class Counter(DurableEntity):
def add(self, amount: int) -> int:
value = self.get_state(int, 0) + amount
self.set_state(value)
return value
outcome = execute_entity(Counter, "add", input=2, state=3)
assert outcome.get_result() == 5
assert outcome.get_state() == 5
assert outcome.actions == ()
For an entity_trigger-decorated function, pass the exposed entity function:
import azure.durable_functions as df
from azure.durable_functions.testing import execute_entity
app = df.DFApp()
@app.entity_trigger(context_name="context")
def counter(context: df.DurableEntityContext) -> None:
value = context.get_state(initializer=lambda: 0)
value += context.get_input()
context.set_state(value)
context.set_result(value)
entity_function = counter.build().get_user_function().entity_function
outcome = execute_entity(entity_function, "add", input=2, state=3)
assert outcome.get_result() == 5
assert outcome.get_state() == 5
The returned EntityTestResult provides get_result() and get_state()
methods plus typed signal or orchestration-start actions scheduled by the
operation. Pass expected_type when reconstructing a custom payload:
assert outcome.get_state(expected_type=CounterState) == CounterState(value=5)
Links
- 2.x samples
- Migration guide from 1.x
- Changelog
- Durable Functions documentation
durabletaskon PyPI- Azure Functions Durable 1.x source
- Azure Functions Python library
- Azure Functions Python worker
- Repository
License
Licensed under the MIT License.
Release files for azure-functions-durable 2.0.0rc2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| azure_functions_durable-2.0.0rc2.tar.gz | 64.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| azure_functions_durable-2.0.0rc2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 142.7 kB
Release files / azure_functions_durable-2.0.0rc2.tar.gz
| Download URL | azure_functions_durable-2.0.0rc2.tar.gz |
|---|---|
| Size | 64.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63192b57f5365a76d982d99d8eb5ea1ec956586c42922f8984ab30746eca868b
|
|
BLAKE2b-256 checksum How to use checksums |
bf3c0676569d3d877827f9ce340c2ee2806aabcc946c8e0ce5e938844200ffef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
RestSharp/106.13.0.0
|
Release files / azure_functions_durable-2.0.0rc2-py3-none-any.whl
| Download URL | azure_functions_durable-2.0.0rc2-py3-none-any.whl |
|---|---|
| Size | 78.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
601f2c5dbabe7167bb59cb754cfbf27b811f6bfcc5493318ce9d71ccd11a4292
|
|
BLAKE2b-256 checksum How to use checksums |
910865d33fc1f0cbee2bb3140ffffc6ec3c6d17c93b6ce27f08ec0b2f12a76c0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
RestSharp/106.13.0.0
|