How to Use Durable Functions in Azure: Simple Guide
Use
Azure Durable Functions to build reliable serverless workflows by defining orchestrator functions that manage state and call activity functions. Deploy your functions in an Azure Function App with the Durable Functions extension enabled to handle long-running processes easily.Syntax
Azure Durable Functions use three main function types:
- Orchestrator function: Controls workflow and calls activities.
- Activity function: Performs tasks like API calls or data processing.
- Client function: Starts the orchestration.
Each function is a separate method with specific triggers.
python
import azure.functions as func import azure.durable_functions as df # Orchestrator function def orchestrator_function(context: df.DurableOrchestrationContext): result1 = yield context.call_activity('ActivityFunction1', 'input1') result2 = yield context.call_activity('ActivityFunction2', result1) return result2 main = df.Orchestrator.create(orchestrator_function) # Activity function def ActivityFunction1(name: str) -> str: return f"Hello, {name}!" # Client function async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse: client = df.DurableOrchestrationClient(starter) instance_id = await client.start_new('orchestrator_function', None, None) return client.create_check_status_response(req, instance_id)
Example
This example shows a simple Durable Function workflow that greets a user and then processes the greeting.
python
import azure.functions as func import azure.durable_functions as df # Orchestrator function def orchestrator_function(context: df.DurableOrchestrationContext): greeting = yield context.call_activity('SayHello', 'Azure User') processed = yield context.call_activity('ProcessGreeting', greeting) return processed main = df.Orchestrator.create(orchestrator_function) # Activity functions def SayHello(name: str) -> str: return f"Hello, {name}!" def ProcessGreeting(greeting: str) -> str: return greeting.upper() # Client function async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse: client = df.DurableOrchestrationClient(starter) instance_id = await client.start_new('orchestrator_function', None, None) return client.create_check_status_response(req, instance_id)
Output
HTTP 202 Accepted with status URLs to check orchestration progress
Common Pitfalls
- Calling non-deterministic code inside orchestrator functions causes errors because orchestrators replay their history.
- Not awaiting activity functions properly can break the workflow.
- Forgetting to enable Durable Functions extension in your Function App leads to deployment failures.
- Using static variables for state inside functions causes incorrect behavior.
python
## Wrong: Calling random inside orchestrator (non-deterministic) import random def orchestrator_function(context: df.DurableOrchestrationContext): value = random.randint(1, 100) # This will cause errors return value ## Right: Call random inside activity function def activity_function(_): import random return random.randint(1, 100) def orchestrator_function(context: df.DurableOrchestrationContext): value = yield context.call_activity('activity_function', None) return value
Quick Reference
Durable Functions key points:
- Orchestrator: controls workflow, must be deterministic.
- Activity: does work, can be non-deterministic.
- Client: starts orchestration, triggers via HTTP or other events.
- Use
yieldfor orchestrator async calls. - Enable Durable Functions extension in Azure Function App.
Key Takeaways
Use orchestrator functions to manage workflow and call activity functions asynchronously.
Keep orchestrator functions deterministic; avoid random or time-based code inside them.
Always enable the Durable Functions extension in your Azure Function App before deploying.
Start orchestrations with client functions triggered by HTTP or other events.
Await all async calls to ensure proper workflow execution.