Microsoft has brought the notions of states to the formerly stateless Azure Functions, Microsoft’s serverless computing platform. The addition of states gives developers exciting new ways to take advantage of Azure Functions.
At first glance, Azure Functions is comparable to Amazon’s AWS Lambda. They both have similar event-driven programming models, but now Azure Functions is starting to show its own colors as a core feature of Azure’s PaaS offering. That’s partly the result of Microsoft’s decision to put Azure Functions at the center of a messaging-driven programming platform, part of a suite of tools that include Service Fabric and the publish-and-subscribe Event Grid.
Adding state to serverless in Azure Functions
The latest update to Azure Functions is an interesting because it takes something that was at its heart stateless and adds state. Where a standard function is best thought of as a software switch—taking data from one input, processing it, and then handling appropriate actions—the new durable functions are what Microsoft is calling “orchestrator functions.” Instead of a single switch, a durable function takes a series of functions and wraps them as a single, long transaction, building in workflow to manage actions, and handling waits by pausing the function.
One of the advantages of Azure Functions is its per-second billing model, where you pay only for the compute you use. That model carries into durable functions, where you’re charged when a workflow is running. If it’s paused waiting for an input, there’s no charge. And when it’s paused, it holds its state externally, so if the host process is reclaimed or the VM that’s hosting the function is rebooted, your function can pick up and carry on.
Keeping Azure Functions states external
Having a way to externalize state is very important, because it’s central to avoiding the workarounds needed to build state in a stateless platform like Azure Functions. When you call into a function, you have no control over where it’s instantiated, and you have no control over how long it’ll be available. If the underlying platform needs to reclaim the container used to host a function, it’s lost. But if it stores state, a replacement function can pick it up and carry on as if it was the same function that stored the data.
Under the hood, durable functions build on familiar Azure concepts, storing state in storage queues and in table storage. But that’s only the start, and you can expect to see alternative storage options in the future, with a focus on improved performance.
New serverless patterns in Azure Functions
Chaining functions is only one option. Where things start to get interesting is using what Microsoft calls fan-out/fan-in patterns. They’re a way of using durable functions to marshal parallel operations, taking in a trigger and launching several functions and waiting for them all to finish before processing the results and using them to trigger a final action.
A task list in the parent durable function tracks all the functions launched as part of the fan-out operation, triggering when they’re all complete. The fan-out actions are checkpoints, recording state and pausing the parent durable function while its child processes run.
When you look at durable functions in detail, you can see that they’re very similar to the reliable actors used in Service Fabric. That similarity is very clear when you look at the some of the more complex design patterns offered, like the stateful singleton. Here, a basic durable function operates as an infinite loop, taking and processing multiple inputs. Processed data is written out as state information, which can be accessed by other code. The durable function that implements the stateful singleton pattern runs only when it receives an appropriate input, and it pauses while it waits for further triggers.
Connecting serverless in Azure Functions to the world
The original stateless release of Azure Functions made sense if you were using to trigger actions based on changes in Azure platform services. But when you’re using them to work with triggers from your own code and third-party code, and with external services and devices, you need some form of state and some idea of workflow because you won’t have any control over response latency. That becomes even more important when you’re waiting for events from internet of things (IoT) hardware, when you have no idea when that data will arrive.
Much of your code is likely workflow code, automating interactions between subroutines and services. Durable functions lets you treat serverless code in the same way, sourcing and sinking events as they occur, aggregating and chaining them as required. They may not solve all your distributed programming problems, but they go along way to reducing complexity—and possibly even saving you money in your cloud applications.
Azure Functions are no longer just in the cloud
Microsoft is making Azure Functions portable. An Azure Functions runtime is available for your own containers, so you can build and deploy serverless applications on your internal network or another public cloud. You won’t get the benefit of Azure’s management tools, but it’s a useful way of ensuring your serverless code runs anywhere you want. There’s also Azure Functions support on Azure Stack, for hybrid cloud deployments.
Initially, though, you won’t see durable functions in the portable Azure Functions runtime; Microsoft plans to support them later. For now, durable functions require Azure services to operate.
Serverless computing models need an effective workflow engine, and by treating durable functions as a programmable workflow, you gain a tool that can help build much more complex orchestrations. Used with other Azure services, like CosmosDB and Service Fabric, as well as with the recently enhanced Kubernetes-based Windows container services, it’s the key to delivering distributed applications running across Azure. For a global public cloud, these stateful functions are going to be indispensable.