Skip to main content
Pre-release

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.

DurableFunctionsClient and SyncDurableFunctionsClient inherit OrchestrationQuery.task_hub_names for filtering orchestration queries by one or more task hubs. Filtering support depends on the backend.

EntityInstanceId and the compatibility EntityId are immutable and hashable, so they can be used as dictionary keys or set elements. Construct a new ID instead of assigning or deleting attributes on an existing ID.

Unicode JSON serialization

By default, durable payloads preserve the shared azure-functions codec's ASCII-escaped JSON representation. With azure-functions>=2.4.0b1, opt in to literal Unicode JSON on the root DFApp at startup:

import azure.durable_functions as df

app = df.DFApp()
app.configure_serialization(ensure_ascii=False)

The shared df_dumps(..., ensure_ascii=...) API was released in azure-functions 2.4.0b1, which is the minimum required shared SDK version. Dependency installation selects a compatible release automatically. If an older SDK is manually installed despite that requirement, configuring the opt-in raises RuntimeError rather than silently ignoring it. Leaving the option unset, or explicitly choosing ensure_ascii=True, preserves the existing JSON encoding.

There is one encoding policy per Python worker process. It applies to both synchronous and asynchronous durable clients, orchestration and entity workers, activity binding outputs, and all registered blueprints, including handlers created before configuration. Configure every scaled-out worker consistently before invocations. Repeating the same setting is allowed; a conflicting setting or changing the policy after the first durable JSON serialization raises ValueError.

Literal Unicode reduces escaping overhead for non-Latin text. For example, a JSON object containing 100,000 Cyrillic characters occupies approximately 200,012 UTF-8 bytes rather than 600,012 ASCII-escaped bytes. Actual reduction depends on the payload. The shared codec preserves surrogate-code-unit and ASCII DEL escapes, custom-object envelopes, and strict/loose typing semantics. This option does not normalize Unicode or change the decoder; existing escaped payloads remain readable.

The policy applies before large-payload externalization, so uploads use the selected JSON encoding and size thresholds use its serialized UTF-8 bytes. Reduced escaping does not eliminate aggregate request limits or replace externalization. Protocol envelopes, reference tokens, management responses, and JSON serialized explicitly by application code are not reformatted by this setting.

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)

License

Licensed under the MIT License.

Metadata

Release files for azure-functions-durable 2.0.0rc4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for azure-functions-durable 2.0.0rc4
File Size Uploaded Provenance Actions
azure_functions_durable-2.0.0rc4.tar.gz 67.7 kB Without provenance Details for azure_functions_durable-2.0.0rc4.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for azure-functions-durable 2.0.0rc4
File Interpreter ABI Platform Actions
azure_functions_durable-2.0.0rc4-py3-none-any.whl Python 3 none any Details for azure_functions_durable-2.0.0rc4-py3-none-any.whl

Total release size: 147.7 kB

Release files / azure_functions_durable-2.0.0rc4.tar.gz

Download URL azure_functions_durable-2.0.0rc4.tar.gz
Size 67.7 kB
Tags Source
SHA-256 checksum
How to use checksums
b19be2eb3f144187879a6accc9994dacbfe42e3cbe1d21d6c6f2e2405afe3fb5
BLAKE2b-256 checksum
How to use checksums
b26fded7d7d206d3b8886bfb56e1f2f24b0773d7831d3a7708b14a831658a7bb
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.0rc4-py3-none-any.whl

Download URL azure_functions_durable-2.0.0rc4-py3-none-any.whl
Size 80.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9fd7982e03d03824d5518dbda0db99da7c9730b803c71fb83e798a191dfeae6c
BLAKE2b-256 checksum
How to use checksums
f71c87740e67d63888e081204bce322fd27b1f3081de7e63fe45af2eac42c8a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via RestSharp/106.13.0.0

Security for azure-functions-durable 2.0.0rc4

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page