Callon Campbell gave a presentation on building stateful serverless orchestrations with Azure Durable Functions. The presentation covered an introduction to serverless computing challenges, an overview of Durable Functions and how it addresses challenges through stateful orchestrations. It included demos of function chaining and fan-out/fan-in patterns using Durable Functions. The presentation also discussed alternate Durable Functions storage providers like Netherite and SQL Server that provide higher performance and portability compared to the default Azure Storage.
[2024]Digital Global Overview Report 2024 Meltwater.pdf
Build stateful serverless apps with Azure Durable Functions
1. Building stateful serverless orchestrations
with Azure Durable Functions
Callon Campbell
Microsoft MVP | Azure
@flying_maverick
2. About me
Callon Campbell
Azure Architect | Developer
Adastra
Microsoft MVP | Azure
20 years enterprise development with Microsoft technologies – .NET (C#),
Azure, ASP.NET, Desktop, SQL, and Mobile
Passionate about serverless and cloud-native application development,
with focus on app migration and modernization, app integration and data
analytics
Blogging at https://TheFlyingMaverick.com
Speaker at community events and meetups
Organizer of “Canada’s Technology Triangle .NET User Group” in Kitchener,
Ontario
8. Azure Functions Hosting Models
In-process
Migrate from .NET Core 3.1 in-
process
Need Durable Functions or
“rich” SDK type bindings
Isolated process
Migrate from .NET 5 or .NET 6
isolated process
Durable Functions now
supported in .NET 7*
Which one do I use?
10. Pattern #1: Function chaining
Problems:
• No visualization to show relationships between functions and queues
• Middle queues are an implementation detail – conceptual overhead
• Error handling adds a lot more complexity
11. Pattern #2: Fan-out/fan-in
Problems:
• Fanning-out is easy, but fanning-in is significantly more complicated
• Functions offers to help with this scenario today
• All the same problems as the previous pattern
12. Introducing Durable Functions
Durable Functions is an extension of Azure Functions and is built on
top of the Durable Task Framework.
Enables you to write long-running orchestration as a single function,
that is reliable, event-driven, and is stateful.
Simplifies complex, stateful coordination requirements in serverless
applications
Execution state is saved in an Azure Storage account, ensuring that
functions could recover automatically from any infrastructure failure
Supports .NET (C#/F#), Java, JavaScript, TypeScript, Python, and
PowerShell.
13. Application Patterns
The primary use case for Durable Functions is simplifying complex,
stateful coordination requirements in serverless applications.
Typical application patterns that can benefit from Durable Functions:
Function chaining
Fan-out/fan-in
Async HTTP APIs
Monitoring
Human interaction
Aggregartor (stateful entities)
20
15. Event Sourcing Log
Durable Functions uses a pattern called “Event Sourcing” to store state
in a backing storage account, which is how its made durable.
16. “Hello Amsterdam!”
[“Hello Amsterdam!”]
Orchestrator
Function
Activity
Function
Execution
History
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", “Amsterdam"));
return outputs;
Orchestrator
Function
?
Activity
Function
“Hello Amsterdam!”
Orchestrator Started
Execution Started
Task Scheduled, SayHello, “Amsterdam”
Orchestrator Completed
Task Completed, “Hello Amsterdam!”
Orchestrator Started
Execution Completed, ["Hello Amsterdam!"]
Orchestrator Completed
How does it work?
17. Orchestration Constraints
Orchestrator code must be deterministic
Never use random numbers, DateTime.UtcNow, Guid.NewGuid(), etc.
Use DurableOrchestrationContext.CurrentUtcDateTime
Orchestrator code should be non-blocking. Never do I/O directly in
the orchestrator
Do I/O in activity functions
Don't write infinite loops
Use DurableOrchestrationContext.ContinueAsNew()
20. Demo 3 – Star Wars API!
Function Fan-out / Fan-in
21. New Storage Providers
Support for two new backend storage providers for storing durable runtime state,
“Netherite” and Microsoft SQL Server (including full support for Azure SQL
Database).
These new storage options allow you to:
• Run at higher scale
• Greater price-performance efficiency
• Greater portability compared to the default Azure Storage configuration
22. Limitations of Azure Storage Provider
Azure Storage has the following limitations:
• Limits on the number of transactions per second
• Strict data size limits for queue messages and Azure Table entities
• Hard to predict costs
• Can’t easily support certain enterprise business continuity requirements, such
as backup/restore and disaster recovery without data loss
• Azure only
23. Introducing “Netherite”
• The Netherite name originates from the world of Minecraft
• Developed by Microsoft Research, it combines Azure Event Hubs
with the FASTER database technology on top of Azure Page Blobs
• Supports significantly higher-throughput of orchestrations and
entities compared to other Durable storage providers
• More cost-effective for high-throughput loads
24. Performance
Benchmark
Single Azure Event Hubs throughput unit (1 TU), costing approximately $22/month USD on the Standard plan, running a
simple function-chaining sample with 5 activity calls running on the Azure Functions Elastic Premium plan.
25. Introducing SQL Server Provider
• SQL Server provider allows Durable Functions to run anywhere
• Azure SQL Database
• On-premises
• Docker Containers / Kubernetes
• IaaS
• Multi-Cloud
• Leverage your existing SQL Server investments
• Backup/restore
• Failover
• Encryption
• Compliance
• Easily integrate with existing SQL-based applications
27. Choosing the right storage provider
Azure Storage
Generally available
Dependencies:
Azure Storage Account
(general purpose v1)
Minimal setup
Lowest minimum cost
Consumption plan: Yes
Elastic Premium plan: Yes
Disconnected support: No
Netherite
Generally available
Dependencies:
Azure Event Hubs
Azure Storage Account
Max throughput
Lower cost at scale
Consumption plan: No
Elastic Premium plan -
requires runtime scale
monitoring
Disconnected support: No
SQL Server
Generally available
Dependencies:
SQL Server 2019 or Azure
SQL Database
Runs anywhere
Enterprise friendly
Consumption plan: No
Elastic Premium plan-
requires runtime scale
monitoring
Disconnected support: Yes
28. In closing
Input/output of functions should be serializable.
Orchestration Functions can only call Activity Functions in the same
Function App.
Don’t use an orchestration function to call a single activity function.
Keep your orchestrations small.
What changes together should be deployed together.
Azure Durable Functions make managing state and complex
workflows easy and familiar.
29. What’s New
Durable Function’s support for .NET 7.0 running in the isolated
worker process is now generally available (supports .NET 6.0 and
.NET Framework too!)
However, not all features from in-process Durable Functions have
been migrated to the isolated worker. Known missing features are:
Durable Entities
CallHttpAsync
Serverless is the culmination of several iterations of cloud platforms. The evolution began with physical metal in the data center and progressed through Infrastructure as a Service (IaaS) and Platform as a Service (PaaS).
Quick overview of Azure Functions
- Don’t have to worry about infrastructure, that’s handled for you.
- It will scale from not running to 1000s of instances and back down as needed.
- As it scales you only pay for what you use.
Dynamically and elastically scale to meet demand.
Allows you as the developer get to focus on the fun stuff…your code and business logic. Everything else is taken cared for you.
This drastically increases time to market.
At the center of serverless is FaaS.
Break it up into single responsibility.
No state…but when you require state it gets tricky.
Over the years we have seen an accelerated shift to adopting serverless and cloud native application architectures. Benefits to these architectures include decreased infrastructure costs and improved time to market, however it's still important to consider high availability and resiliency in your application design. In this session, Callon will talk about developing scalable enterprise serverless applications on Azure with .NET and use a real world example of a solution he developed and running in production.
Function as a service (FaaS) platforms present a small delay on their first executions, known as cold start. This makes it challenging to adopt serverless functions for mission critical apps where a few seconds can make a huge difference.
Instead of billing per execution & mem used, Premium is based on the number of core seconds and mem used across warm and needed instances.
Regardless of the function app timeout setting, 230 seconds (4min and 50sec) is the maximum amount of time that an HTTP triggered function can take to respond to a request. This is because of the default idle timeout of Azure Load Balancer. For longer processing times, consider using the Durable Functions async pattern or defer the actual work and return an immediate response.
Better hardware, you can do a lot more now.
Elastic scaling, bursts out nicely
Networking options – I didn’t have time to show this but service endpoints and VNET integrations
Reserved instance, helps with the cold start and long running. And custom containers.
Functions is open source – runtime, core tools, docker images.
Run it locally, its exactly what you see in the cloud. Very easy to get going and publish.
Publish to Azure Functions services – consumption, app service, and premium (best of both worlds)
There is also other places to run functions – Raspberry Pi, Kubernetes cluster, or on non-azure hosts and on-prem.
For .NET, Azure Functions supports both in-process and isolated (out-of-process) execution models. Choose in-process if you are upgrading from .NET Core 3.1 Azure Functions or if you are looking for features, such as Durable Functions, that are currently only available to in-process apps.
Isolated function apps provide more control of the function worker process and greater compatibility with libraries.
Some sequencing that needs to happen and I have to chain them all together.
If I want to parallel some work and then pull in the results into one function
Waiting for external events
Watcher pattern
Long running http requests
Human interaction and I don’t want to wait forever…I want a timeout.
The answer to some of these is I don’t know. Let’s take a look at two patterns and how we can solve them
Is an extension of Azure Functions and is built on top of the Durable Task Framework
Allows you to write long-running, reliable, event-driven, and stateful logic while simplifying complex, stateful coordination in serverless applications
The execution state is saved in an Azure Storage account, ensuring that functions can recover automatically from any infrastructure failure
Ideal for situations where you want to chain functions together, fan-out/fan-in, HTTP API Async, Monitoring, Waiting on user interaction
They automatically checkpoint their progress whenever the function awaits. Local state is never lost if the process recycles or the VM reboots.
In Durable Functions we introduce the concept of an orchestrator function.
The starter function triggers the orchestrator to start the execution. Often this starter function is an Http endpoint. Once the starter has called the orchestrator function, it goes to sleep for the rest of the day or until it’s triggered again. This reduces the cost significantly.
The orchestrator function is responsible for calling and receiving the output of the activity functions (what you know as normal functions).
The activity function output becomes part of the local state of the orchestrator function.
So how does this all work?
23
Orchestrator code must be deterministic, as it will be replayed multiple times and must produce the same result each time.
.NET 7 with the new isolated process hosting model
.NET 6 with the old in-process hosting model
Azure Durable Functions now supports two new backend storage providers for storing durable runtime state, “Netherite” and Microsoft SQL Server (including full support for Azure SQL Database).
These new storage options allow you to:
Run at higher scale
Greater price-performance efficiency
Greater portability compared to the default Azure Storage configuration
The default Azure Storage configuration provider does have some limitations:
Has limits on the number of transactions per second for a storage account
Has strict data size limits for queue messages and Azure Table entities
Costs can be hard to predict since they are per-transaction and have very limited support for batching
Can’t easily support certain enterprise business continuity requirements, such as backup/restore and disaster recovery without data loss
Can’t be used outside of the Azure cloud
Looking at the GitHub repos - “Netherite” comes from the world of Minecraft and is the name of a rare material that is more durable than diamond, can float in lava, and cannot burn.
The Netherite storage provider aspires to have similar qualities, but in the context of Durable Functions.
Developed by Microsoft Research, it combines Azure Event Hubs with the FASTER database technology that sits on top of Azure Page Blobs
Supports significantly higher-throughput and is more cost-effective for high-throughput loads
The orchestrator used in this test is a simple function-chaining sample with 5 activity calls running on the Azure Functions Elastic Premium plan.
As you can see the Netherite provider has considerable throughput compared to Azure Storage.
While the Netherite provider was designed for maximum throughput, the Microsoft SQL Server provider for Durable Functions is designed for the needs of the enterprise, including the ability to decouple from the Azure cloud.
With the ability to run Microsoft SQL anywhere, including on-premises servers, Edge devices, Linux Docker containers, on the Azure SQL Database serverless tier, and even on competitor cloud providers like AWS and GCP. This means you can run Durable Functions anywhere that Azure Functions can run, including your own Azure Arc-enabled Kubernetes clusters.
The design of the Microsoft SQL storage provider for Durable Functions also makes it easy to integrate with existing SQL-based applications. When your function app starts up, it automatically provisions a set of tables, functions, and procedures in the target database within a “dt” schema (“dt” stands for Durable Tasks).
You can easily monitor your orchestrations and entities by running SELECT queries against these tables.
The choice to use storage providers other than Azure Storage should be made carefully. Most function apps running in Azure should use the default Azure Storage provider for Durable Functions. However, there are important cost, scalability, and data management tradeoffs that should be considered when deciding whether to use an alternate storage provider.
Either of these alternate storage providers can be configured without any code changes to your application if you so choose to try them out.