How to combine Azure Durable Functions and HTTP triggered Functions

Peter Dol
3 min readJul 5, 2021

--

Combining HTTP triggered and Durable Azure Functions comes with some performance and scalability challenges. In this blog post I provide some insight into and solutions for these problems.

Azure Durable Functions are a great fit for long running processes. The Durable Functions architecture helps split the work up in multiple activities that can easily be run in parallel. We originally did a lot of nightly batch processing, Durable Functions created a scalable and robust solution for this. But when we needed to reuse this existing functionality in a web app we ran into some performance and scalability problems that forced us to redesign our solution.

Initial setup

At first we decided to simply reuse our existing Activity and Orchestration functions and exposed them via an HTTP triggered function. The resulting function app looked like this:

In the beginning this was working OK, but in moments of high load, especially when some of our scheduled jobs were also running, response times would degradate. The HTTP triggered functions and the scheduled functions use the same Durable Functions hub and there is no way to prioritise HTTP requests over batch requests. Online calls would wait for batch processing to finish and we would get a lot of HTTP timeouts. Another drawback of this solution was that HTTP requests were also routed through the Durable Functions hub which had a negative impact on the response times even under normal load.

Refactor to a shared business logic layer

We then decided to no longer use the Orchestration and Activity functions directly from the HTTP triggered function. Instead we refactored the shared functionality to a business logic layer and reused this layer from the HTTP triggered functions as well as the Timer triggered Durable functions. Functions and Activities were kept very simple and included just the necessary Azure Functions boilerplate code. The real work was done in services in the Business Logic Layer. An added benefit of this setup is that the resulting clean business logic layer can be tested a lot more easily without mocking all the durable functions dependencies.

Separate online + batch Function Apps

Another optimalization is to deploy your application as two separate Function Apps in Azure, an online Function App and a batch Function App. This way you can configure your Function Apps according to their specific demands, for example:

  • increase the number of pre-warmed instances for the online Function App
  • increase max instance count for the batch Function App

Conclusion

As a rule of thumb you should try and keep your Function apps as small as possible. A Function App should be dedicated to a specific business function. A lot of thought should be given to how Function Apps should be split up to make sure that outage and performance problems in one Function don’t negatively impact other Functions. Try to separate online and batch functionality. If you need to reuse functionality then the solution from this blog post can help.

--

--

Peter Dol

Freelance software engineer with an interest in .NET, Azure, React and DevOps.