Edit

Share via


Programming model overview

Durable Functions is an extension of Azure Functions that adds stateful orchestration capabilities to your function app. A Durable Functions app is made up of different Azure functions, each playing a specific role: orchestrator, activity, entity, or client. These roles correspond to specialized trigger and binding types that the Durable Functions extension provides.

The Durable Task SDKs let you build stateful, fault-tolerant applications on any compute platform. Your app defines orchestrators, activities, and entities as classes or functions that you register with a worker. A separate client API lets you start and manage orchestration instances.

The following table summarizes the core programming components and their roles:

Component Role Defined by
Orchestrator Coordinates workflow logic Orchestration trigger
Activity Performs a single unit of work Activity trigger
Entity Manages a small piece of state Entity trigger
Client Starts and manages orchestrations and entities Durable client binding
Component Role Defined by
Orchestrator Coordinates workflow logic A class or function registered with the worker
Activity Performs a single unit of work A class or function registered with the worker
Entity Manages a small piece of state A class registered with the worker
Client Starts and manages orchestrations and entities DurableTaskClient API

Orchestrators

Orchestrators define the workflow: what actions to take, in what order, and how to handle the results. You write orchestrator logic as ordinary code using standard control-flow constructs like loops, conditionals, and try/catch blocks.

An orchestrator can schedule several types of tasks:

Orchestrators can also interact with entities.

In Durable Functions, you define an orchestrator by using the orchestration trigger binding. The trigger provides a context object that you use to schedule tasks and receive results.

In the Durable Task SDKs, you define an orchestrator by implementing a class or function and registering it with the Durable Task worker. The orchestrator receives a context object that you use to schedule tasks and receive results.

Important

Orchestrator code must be deterministic. The Durable Task runtime uses event sourcing and replay to rebuild orchestrator state, so nondeterministic code can cause failures or deadlocks. For detailed guidance, see Orchestrator code constraints.

For a complete overview of orchestrator behavior, including replay, instance identity, and error handling, see Durable orchestrations.

Activities

Activities are the basic unit of work in a durable orchestration. Each activity typically represents a single task, such as calling a web API, writing to a database, or computing a result. Orchestrators call activities to do their real work.

Activities differ from orchestrators in key ways:

  • No code restrictions. Orchestrators must be deterministic, but activities can run any code, including nondeterministic or long-running operations.
  • At-least-once execution. The runtime guarantees that each activity runs at least once during an orchestration. If a failure occurs after the activity completes but before the result is recorded, the runtime might rerun it.
  • Single responsibility. Each activity receives one input and returns one output. To pass multiple values, use a complex type or collection.

You define an activity function by using the activity trigger binding. The trigger provides the input that the orchestrator passed when scheduling the activity.

You define an activity by implementing a class or function and registering it with the Durable Task worker. The activity receives the input that the orchestrator passed when scheduling it.

Note

Because activities guarantee only at-least-once execution, make your activity logic idempotent whenever possible. For example, use "upserts" instead of inserts, or check for existing results before creating new resources.

Activities can run serially, in parallel, or in a combination of both.

Entities

Entities manage small, durable pieces of state. Each entity has a unique identity and a set of named operations that can read or update its internal state. Entities differ from orchestrators in that they manage state explicitly through operations instead of implicitly through control flow. They also differ from orchestrators in that they don't have the same code restrictions — entity operations can run any code, including nondeterministic or long-running operations.

Common uses for entities include:

  • Aggregating data from multiple sources
  • Implementing distributed locks or semaphores
  • Modeling stateful objects like shopping carts or game sessions

Entities run operations serially: only one operation runs at a time for a given entity instance. This serial execution prevents concurrency conflicts without requiring explicit locking.

You define an entity function by using the entity trigger binding.

Note

Entity functions are supported in .NET, JavaScript/TypeScript, Python, and Java, but not in PowerShell.

You define an entity by implementing a class and registering it with the Durable Task worker.

Note

Entity support is available in the .NET, JavaScript/TypeScript, and Python SDKs. The Java SDK doesn't currently support entities.

For a complete guide to defining, calling, and managing entities, see Durable entities.

Client

The client component is how you interact with orchestrations and entities from outside the orchestration. Common client operations include:

  • Scheduling new orchestration instances
  • Querying the status of running or completed orchestrations
  • Raising events to waiting orchestrations
  • Suspending and resuming orchestration instances
  • Terminating orchestration instances
  • Signaling entity operations and reading entity state

Any non-orchestrator function can act as a client function. What makes it a client is the use of the durable client output binding. For example, you can start an orchestration from an HTTP-triggered function, a queue-triggered function, or a timer-triggered function.

The durable client binding also provides APIs for interacting with entities, including signaling entity operations and reading entity state. For more information, see the entity client binding.

In the Durable Task SDKs, you interact with orchestrations and entities through the DurableTaskClient class. You create a client instance in your application code and call its methods to start, query, or manage orchestration and entity instances. The client can be used from any part of your application — an HTTP endpoint, a background service, a console app, or any other code.

For detailed information on all instance management operations, including code samples for each language, see Manage orchestration instances.

Next steps

Get started by creating your first Durable Function app: