Introduction
Three years ago, after the release of Azure Durable Functions, I wrote a post comparing the capabilities of Logic Apps and Durable Functions. Both service offerings provide orchestration capabilities on Azure. At that time, Azure Durable Functions had just been released as generally available. As you’d expect, many things have changed since then. Fast forward to 2021, a new tier of Logic Apps has been released, the Standard SKU.
During these three years, both platforms have evolved, and I keep hearing people wondering about how to choose between the two to build stateful workflows. Thus, I’ve decided to write an updated version of this comparison aiming at providing some decision guidelines for solution architects and developers.
In this post I’ll be comparing Logic Apps Standard and Durable Functions 2.x, and won’t be considering Logic Apps consumption nor the Integration Service Environment tiers. I’ll follow a similar structure to the one I used three years ago covering the sections below.
- Development Experience and Continuous Delivery
- Orchestration Capabilities
- Connectivity Capabilities
- State Management
- Hosting and Execution Capabilities
- Management and Monitoring
- Pricing
Development Experience and Continuous Delivery
Each platform has a very different development experience. For some developers, this might be one of the most important factors when deciding the platform to choose. However, I would argue that in most cases, we need to think beyond the development phase and consider how the solution will be managed, troubleshoot, and monitored once in production. In this section, I’ll compare different aspects of the development experience for each platform and will leave the operations side for a later section.
|
Durable Functions |
Logic Apps |
Approach |
Codeful (imperative code) |
Low-code (declarative via a visual designer) |
Supported languages |
At the time of writing, Durable Functions supports: C#, NodeJS, Python, F#, and PowerShell |
Workflows are implemented using a visual designer. Behind the visual representation of the workflow, there is a JSON-based workflow definition language. |
Local development and debugging |
Azure Functions can be developed and debugged offline with the local runtime and a storage emulator. |
Logic Apps workflows can be developed and debugged locally using VS Code. |
Continuous delivery |
Continuous delivery can be implemented using Azure DevOps, GitHub, or any other release management tool that supports Azure CLI or PowerShell. |
Logic Apps can be deployed using Azure DevOps, GitHub, or any other release management tool that supports Azure CLI or PowerShell. One of the key improvements introduced by Logic App Standard is the ability to parameterise environment variables via application settings. |
Orchestration Capabilities
The orchestration capabilities of each platform are quite different. While the underlying implementation is abstracted from us in both platforms, it is relevant to understand how they work internally. How both engines work and how some workflow patterns are supported are described in the table below.
|
Durable Functions |
Logic Apps |
Orchestration trigger |
A workflow or orchestration function instance can be instantiated by client function, which in turn can be triggered using any of the available trigger bindings. |
A Logic App workflow can be initiated by the many different available connectors that support triggers. |
Actions being orchestrated |
An orchestration function can call activity functions and sub-orchestrations. Activity functions can implement any of the supported output bindings. |
Many different workflow actions can be orchestrated. Logic Apps workflows can invoke actions offered by the 450+ connectors or call nested Logic App workflows. |
Flow control |
In Durable Functions, the workflow's flow is controlled using standard code constructs, such as conditions, switch-case statements, loops, try-catch blocks, etc. |
You can control the flow with conditional statements, switch statements, loops, scopes, and controlling activity chaining using the runAfter property. |
Programmatic instance management |
Durable Functions instances can be managed using the management API or the orchestration client as described here. |
While there is a management API for instance management in Logic Apps consumption, at the time of writing, there is no API with similar functionality for Logic Apps Standard. |
Concurrency control |
Concurrency throttling is supported. |
Concurrency control can be configured at workflow level or loop level. |
Error handling |
Error handling is implemented as part of the orchestrator function. |
Error handling is done using retry policies and runAfter behaviour. |
Chaining pattern |
Functions can be executed in a sequence and outputs of one can be inputs of subsequent ones. |
Actions can easily be chained in a workflow. Additionally, the runAfter property allows executing actions based on the status of a previous action or scope. |
Fan-out / fan-in pattern |
Functions can be executed in parallel and the workflow can continue when all or any of the branches finish. |
You can fan-out and fan-in actions in a workflow by implementing parallel branches, or for each loops running in parallel. |
Async HTTP APIs pattern |
Client applications or services can invoke Durable Functions orchestrations via HTTP APIs and get the orchestration status asynchronously. Additionally, you can set a custom status value that could be queried by external clients. |
The HTTP response action in Logic Apps supports asynchronous calls. You can configure it to return a HTTP 202 accepted status and a location header to retrieve the running state asynchronously. |
Monitor pattern |
The monitor pattern can be implemented as described here. |
The monitor pattern can be implemented using the until loop. Additionally, all HTTP-based actions follow the standard asynchronous operation pattern. |
Approval workflow (human interaction) pattern |
The approval or human Interaction pattern can be implemented as described here. |
Approval workflows can be implemented with the out-of-the-box connectors or custom as described here. |
Aggregator pattern |
The aggregator pattern can be implemented using durable entities. |
To implement the aggregator pattern on Logic Apps, an external data store is required. |
Connectivity Capabilities
Logic Apps have been built with a key focus on integration. Thus, connectivity is one of its strengths. However, not all scenarios require connecting to many different systems and Durable Functions might have all that you need. The connectivity capabilities of each service offering are contrasted in the table below.
|
Durable Functions |
Logic Apps |
Connectors and bindings |
At the time of writing, Azure Functions provides 16 supported bindings. Some of these bindings can trigger a function, while others can provide inputs or outputs. Additionally, as Azure Functions can be triggered by Event Grid events, any Event Grid source can potentially become a trigger for Azure Functions. |
At the time of writing, Logic Apps provide more than 450 connectors, and the list keeps growing. Among these, there are protocol connectors, Azure Services connectors, Microsoft SaaS connectors, and third-Party SaaS Connectors. Some of these connectors can trigger Logic App workflows, while others support getting and pushing data. |
Custom connectors |
You can create custom bindings for Azure Functions. |
Logic Apps allow you to build custom connectors based on a connector extensibility model. |
Network capabilities |
Azure Functions hosted on premium, dedicated plans, or an App Service Environment have multiple networking capabilities, including inbound access restrictions, VNet integration, hybrid connections, and outbound restrictions. |
Given that Logic Apps Standard is hosted on the Azure Functions runtime, similar networking capabilities are available. It is worth noting that only the built-in connectors are executed within the network context. At the time of writing the built-in connectors include Azure blob, Azure Functions, DB2, Event Hubs, HTTP, IBM Host File, MQ, Service Bus, and SQL Server. Additionally, Logic Apps offers the on-premises data gateway, which, through an agent installed on a virtual machine in a private network, allows you to connect to a list of supported protocols and applications. |
State Management
There are some differences in how each platform manages its state. These are discussed in the table below.
|
Durable Functions |
Logic Apps |
Storage providers |
At the time of writing, Azure storage is the only supported storage provider for production workloads. However, SQL Server and Event Hubs via Netherite are available in preview. |
Azure storage is supported as GA for storing the workflow state. Additionally, SQL Server is available in preview. |
Shared state across instances (data state) |
Durable entities can be leveraged to share states across instances. |
Many polling triggers, e.g., file system, SQL, etc., have a state that is shared across instances. However, Logic Apps does not offer built-in support for shared custom states across instances. If that is a requirement, you would need to rely on external storage services. |
Hosting and Execution Capabilities
Relevant hosting features and execution capabilities are compared in the table below.
|
Durable Functions |
Logic Apps |
Run duration limits |
One instance can run without defined time limits unless there are retention limitations in the storage provider (see state management section). |
In Logic Apps Standard, the maximum workflow run duration can be configured in the host.json file. |
Hosting |
Azure Functions can run as managed PaaS on Azure, but also on-premises or third-party clouds using Azure Arc (currently in preview). |
Logic Apps can run as managed PaaS on Azure, but also on-premises or third-party clouds using Azure Arc (currently in preview) |
Versioning |
When deploying a new version with breaking changes different mitigations strategies can be implemented. |
When a new workflow version is deployed, in-flight workflows will continue working on the version they started with. |
Throughput |
Durable Functions can be tuned for higher throughput. For high throughput scenarios, the Netherite storage provider is recommended (currently in preview). |
Logic Apps can be configured to have lower latency with stateless workflows. However, expect Logic Apps to have considerably slower response times compared to Durable Functions. |
Management and Monitoring
Each platform offers different management and monitoring tools as described in the table below.
|
Durable Functions |
Logic Apps Standard |
Tracing and logging |
Durable Functions has native integration with Application Insights that provides built-in tracing. Additionally, you can implement application-level custom tracing. These traces can be queried, and charts can be rendered using KQL. |
Logic Apps Standard offers native integration with Application Insights. These traces can be queried, and charts can be rendered using KQL. |
Monitoring |
A community-built monitor is available to monitor Durable Functions. |
Logic Apps allow you to monitor and view the run history of stateful workflows. |
Instance resubmission |
Failed instances can be rewound, currently in preview support. |
Logic Apps allows you to resubmit a failed message from the run history. |
Pricing
Considering that Logic Apps Standard runs on top of the Azure Functions runtime, pricing is not very similar. However, Logic Apps Standard does not currently support pay-per-use. Pricing details of each platform are compared in the table below.
|
Durable Functions |
Logic Apps Standard |
Pay-per-use |
Can run in a pay-per-use consumption-based plan. |
Currently, there is no consumption plan for Logic App Standard. |
Instance-based plans |
Durable Functions can run in a premium plan, app service plan, or an App Service Environment. |
Logic Apps can run in workflow standard plans and App Service Environments. |
Wrapping-Up
In this post, I’ve contrasted some features of both Durable Functions and Logic Apps Standard. Considering that now Logic Apps Standard runs on top of the Azure Functions runtime, both services are much more similar than they were before. However, depending on the requirements or even personal preferences, an architect or developer might prefer one or the other. Below, I try to provide some decision guidelines summarising the comparison presented above.
Logic Apps are usually better suited for the following scenarios:
- Enterprise application and B2B integration solutions that would benefit from the 450+ available connectors.
- Rich built-in monitoring tools are required.
- A low-code approach with a visual designer is preferred over code.
- Asynchronous processes in which low response times is not a must.
- It is acceptable to pay for a dedicated hosting plan.
In contrast, Durable Functions are typically a better fit in the scenarios below.
- The available bindings suffice to meet the connectivity requirements.
- The available community-built monitoring tool meets the monitoring requirements.
- A codeful approach is preferred or complex workflow constructs are required.
- High throughput and low latency scenarios.
- A consumption plan is preferred for cost optimisation.
It is also worth noting that in some cases you might not need to choose one over another, but leverage both to build your solution, as both can complement each other.
I hope this post has provided you with useful information and that you are better prepared to choose the right platform to use in your next project.
Happy clouding!
Cross-posted on Paco’s Blog.
Follow Paco on @pacodelacruz.