You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
Standard Azure Functions are stateless — each invocation is independent with no built-in way to coordinate multiple steps, wait for external events, or manage long-running workflows. Durable Functions is an extension that adds stateful orchestration capabilities, enabling you to write complex workflows as code. This lesson covers orchestrator functions, activity functions, patterns, and best practices.
Durable Functions is an extension of Azure Functions that lets you write stateful functions in a serverless environment. The extension manages state, checkpoints, and restarts automatically using an Azure Storage backend.
The framework introduces three new function types:
| Function Type | Purpose |
|---|---|
| Orchestrator | Defines the workflow — calls activities, waits for events, manages control flow |
| Activity | A single unit of work within the workflow — the actual business logic |
| Entity | A stateful object that can be read and updated (actor model) |
| Client | Starts orchestrations or sends events to running instances |
Durable Functions uses an event-sourcing and replay architecture:
await (e.g., calling an activity)Execution 1: [Start] → [Call Activity A] → checkpoint → unload
Execution 2: [Start] → [Activity A result from cache] → [Call Activity B] → checkpoint → unload
Execution 3: [Start] → [A cached] → [B cached] → [Call Activity C] → checkpoint → unload
Execution 4: [Start] → [A cached] → [B cached] → [C cached] → [Return result] → complete
This replay mechanism allows orchestrations to run for minutes, hours, days, or even months without holding a function instance in memory the entire time.
The orchestrator defines the workflow:
const df = require('durable-functions');
df.app.orchestration('processOrderOrchestrator', function* (context) {
const order = context.df.getInput();
// Step 1: Validate the order
const isValid = yield context.df.callActivity('validateOrder', order);
if (!isValid) {
return { status: 'rejected', reason: 'Validation failed' };
}
// Step 2: Process payment
const payment = yield context.df.callActivity('processPayment', order);
// Step 3: Ship the order
const shipment = yield context.df.callActivity('shipOrder', {
orderId: order.id,
paymentId: payment.id
});
// Step 4: Send confirmation
yield context.df.callActivity('sendConfirmation', {
orderId: order.id,
trackingNumber: shipment.trackingNumber
});
return { status: 'completed', trackingNumber: shipment.trackingNumber };
});
Each activity performs a single unit of work:
df.app.activity('validateOrder', {
handler: async (order) => {
// Validate inventory, customer, pricing
return order.items.length > 0 && order.total > 0;
}
});
df.app.activity('processPayment', {
handler: async (order) => {
// Call payment gateway
return { id: 'pay_' + Date.now(), amount: order.total };
}
});
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.