Azure Durable Functions vs Logic Apps: How to choose?
Introduction
Azure currently has two service offerings of
serverless compute: Azure Logic Apps and Azure Functions. Until recently, one could argue that
Azure Functions were code triggered by events while Logic Apps were
event-triggered workflows. However, that changed after the release of Azure Durable Functions which have reached General Availability very
recently. Durable Functions is an extension of Azure Functions that allows you
to build stateful and serverless code-based workflows. With Azure Logic Apps you
can create stateful and serverless workflows through a visual designer.
If you are architecting a solution that requires
serverless and stateful workflows on Azure, you might be wondering how to
choose between Azure Durable Functions and Logic Apps. This post aims to shed
some light to select the platform that better suits your needs.
Development
For some people the development experience might be
a very key factor when deciding a platform over the other. The development
experience of both platforms is quite different as described below:
Durable Functions
|
Logic Apps
|
|
Paradigm
|
Imperative code
|
Declarative code
|
Languages
|
At the time of writing only C# is officially supported.
However, you can make them work with F# and
JavaScript support is currently in preview.
|
Workflows are implemented using a visual designer on the Azure Portal or Visual Studio. Behind the
visual representation of the workflow, there is the JSON-based Workflow Definition
Language.
|
Offline Development
|
Can be developed offline with the local runtime and Storage emulator.
|
You need to be online with access to the Azure to be able to develop
your workflows.
|
Durable Functions allow you to use imperative code
you might already be familiar with, but you still need to understand
the constraints of this extension. Logic Apps might require you to learn to use
a new development environment, but which is relatively straight forward and
quite handy for scenarios where less coding is the preference.
Connectivity
Logic Apps is an integration platform,
thus, it truly offers better connectivity than Azure Durable Functions. Some
details to consider are described in the table as follows.
Durable Functions
|
Logic Apps
|
|
Connectors or Bindings
|
The list of supported bindings is here. Some of these
bindings support triggering a function, or are inputs or outputs. The list of
bindings is growing, especially for the Functions runtime version 2.
Additionally, as Azure Functions can be triggered by Event Grid
events, any Event Grid Publishers can
potentially become a trigger of Azure Functions.
|
Logic Apps provide more than 200 connectors,
and the list just 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 as part of the workflow.
|
Custom Connectors
|
You can create custom input and output bindings for
Azure Functions.
|
Logic Apps allow you to build custom connectors.
|
Hybrid Connectivity
|
Azure Functions hosted on a App Service Plan (not consumption plan)
support Hybrid Connections.
Hybrid connections allows to have a TCP tunnel to access on-premises systems
and services securely.
Additionally, Azure Functions deployed on an App Service Plan can
be integrated to a VNET or
deployed on a dedicated App Service Environment to
access resources and services on-premises.
|
Logic Apps offers the On-Premises Data Gateway,
which, through an agent installed on-premises, allows you to connect to a
list of supported protocols and applications.
It’s worth mentioning that the Product Team is currently working on
Isolated Logic Apps, which will **in the future** be
deployed on your own VNET, thus will have access to resources on-premises,
which will unlock many scenarios.
|
Workflow
Both workflow engines are quite different. Even
though the underlying implementation is abstracted for us, it’s important to
know how they work internally when architecting enterprise-grade solutions. How
both engines work and how some workflow patterns are supported is described
below.
Durable Functions
|
Logic Apps
|
|
Trigger
|
A workflow instance can be instantiated by any Azure Function
implementing the DurableOrchestrationClient.
|
Can be initiated by the many different available triggers offered by
the connectors.
|
Actions being orchestrated
|
Can orchestrate Activity Functions (with the ActivityTrigger attribute).
However, those Activity Functions could call other services, using any of the
supported bindings.
Additionally, orchestrations can call sub-orchestrations.
At the time of writing, an orchestration function can only call
activity functions that are defined in the same Function App. This could
potentially hinder reusability of services.
|
Many different workflow actions can
be orchestrated. Logic Apps workflows can be calling actions of the more than
200 connectors, workflow steps, other Azure Functions, other Logic Apps, etc.
|
Flow Control
|
The workflow’s flow is controlled using the standard code constructs.
E.g. conditions, switch case statements, loops, try-catch blocks, etc.
|
You can control the flow with conditional statements, switch statements, loops, scopes and
controlling the activity chaining with the runAfter property.
|
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
to execute 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 simply
implementing parallel branches,
or ForEach loops running
in parallel.
|
Async HTTP APIs and Get Status
Pattern
|
Client applications or services can invoke Durable Functions
orchestration via HTTP APIs asynchronously and later get the orchestration status to learn when
the operation completes. Additionally, you can set a custom status value that
could be query by external clients.
|
Client applications or services could call Logic Apps Management API
to get the instance run status.
However, either the client has to have access to this API or you would need
to implement a wrapper of this.
Custom Status value is not currently supported out-of-the-box. If
required, you would need to persist it in a separate store and expose it with
a custom API.
|
Approval Workflow (Human
Interaction) Pattern
|
The Human Interaction (Approval Workflow) Pattern can be
implemented as described here.
|
Approval Workflows can be implemented with the out-of-the box connectors or
custom as described here.
|
Correlation Pattern
|
The Correlation Pattern can be implemented not only when there is
human interaction, but for broader scenarios in the same way as described
above.
|
The Correlation Pattern can easily be implemented using the webhook action or
with Service Bus sessions.
|
Programmatic instance management
|
Client applications or services can monitor and terminate instances of
Durable Functions orchestrations via the API.
|
Client applications or services could call Logic Apps Management API
to monitor and
terminate instances of Logic App Workflows. However, either the client
has to have access to this API or you would need to implement a wrapper.
|
Shared State across instances
|
Durable Functions support what they call “eternal orchestrations”
which is a way to implement flexible loops with a state across loops without
the need to store the complete iteration run history. However, this
implementation has some important limitations, and the product team suggests
to use only it for monitoring scenarios that
require flexible recurrence and lifetime management and when the lost of
messages is acceptable.
|
Logic Apps does not support eternal orchestrations. However, different
strategies can be used to implement endless loops with a state across
instances. E.g. making use of a trigger state or
storing the state in an external store to pass it from one instance to the
next one in a singleton workflow.
|
Concurrency Control
|
Concurrency throttling is supported.
|
Concurrency control can be configured at workflow level or loop level.
|
Lifespan
|
One instance can run without defined time limits.
|
One instance of Logic Apps can run for up to 90 days.
|
Error Handling
|
Implemented with the constructs of the language used in the orchestration.
|
Retry policies and catch strategies can
be implemented.
|
Orchestration Engine
|
Orchestration functions and activity functions may be running on
different VMs. However, Durable Functions ensures reliable execution of orchestrations.
To support this, check-pointing is implemented at each await statement.
Additionally, the orchestration replays every time after resuming from an
await call until it reaches the last activity check-pointed to rebuild the
in-memory state of the instance. For high throughput scenarios, you
could enable extended sessions.
|
In Logic Apps the runtime engine breaks down the different tasks based
on the workflow definition. These tasks are distributed among different
workers. The engine makes sure that each task is executed at least once, and
that tasks are not executed until their dependencies have finished with the
expected status.
|
Some additional constraints and
considerations
|
The orchestration function has to be implemented with some constraints in mind, such as, the
code must be deterministic and non-blocking, async calls can only be done
using the DurableOrchestrationContext and infinite loops
must be avoided.
|
To control the workflow execution flow sometimes we need advanced
constructs and operations, that can be complex to implement in Logic Apps.
The Worfklow definition language offers some functions that we can leverage, but
sometimes, we need to make use of Azure Functions to perform advanced
operations required as part of the workflow.
Additionally, you need to consider some limits of Logic Apps.
|
Deployment
The deployment of these two platforms also has its
differences, as detailed below.
Durable Functions
|
Logic Apps
|
|
CI/CD
|
Durable Functions builds and deployments can be automated using VSTS build and release pipelines.
Additionally, other build and release management tools can be used.
|
Logic Apps are deployed using ARM Templates as described here.
|
Versioning
|
Versioning strategy is very important in Durable Functions. If you
introduce breaking changes in a new version of your workflow, in-flight
instances will break and fail.
You can find more information and mitigation
strategies here.
|
Logic Apps keep version history of all workflows saved or deployed.
Running instances will continue running based on the active version when they
started.
|
Runtime
|
Azure Functions can not only run on Azure, but be deployed on-premises,
on Azure Stack, and
can run on containers as well.
|
Logic Apps can only run on Azure.
|
Management and
Monitoring
How you manage and monitor each your solutions on
platform is quite different. Some of the features are described in the table as
follows.
Durable Functions
|
Logic Apps
|
|
Tracing and Logging
|
The orchestration activity is tracked by default in Application Insights.
Furthermore, you can implement logging to App Insights.
|
The run history and trigger history are logged
by default. Additionally, you can enable diagnostic logging to
send additional details to Log Analytics. You can also make use of trackedProperties to
enrich your logging.
|
Monitoring
|
To monitor workflow instances, you need to use Application Insights
Query Language to build your custom queries and
dashboards.
|
The Logic Apps blade and Log Analytics workspace solution
for Logic Apps provide very rich and friendly visual tools for
monitoring.
Furthermore, you can build your own monitoring dashboards and queries.
|
Resubmitting
|
There is no out-of-the-box functionality to resubmit failed messages.
|
Failed instances can easily be resubmitted from the Logic Apps blades
or the Log Analytics workspace.
|
Pricing
Another important consideration when choosing the
right platform is pricing. Even though both options offer a serverless option
where you only pay for what you use, there are some differences to consider as
described below.
Durable Functions
|
Logic Apps
|
|
Serverless
|
In the consumption plan, you pay per-second of resource consumption
and the number of executions. More details described here.
|
For workflows you pay per-action and trigger (skipped, failed or
succeeded). There is also a marginal cost for storage.
In case you need B2B integration, XML Schemas and Maps or Liquid
Templates, you would need to pay for an Integration Account.
More details here.
|
Instance Based
|
Durable Functions can also be deployed on App Service Plans or App
Service Environments where you pay per instance.
|
At the moment there is no option to run Logic Apps on your dedicated
instances. However, this will change in the future.
|
Wrapping-Up
This post contrasts in detail the capabilities and
features of both serverless workflow platforms available on Azure. The platform
better suited really depends on the functional and non-functional requirements
and also on your preferences. As a wrap-up, we could say that:
Logic Apps are better suited when
- Building integration solutions and leveraging the very extensive
list of connectors would reduce the time-to-market and ease connectivity,
- Visual tools to manage and troubleshoot workflows are required,
- It’s ok to run only on Azure, and
- A visual designer and less coding are preferred.
And Durable Functions are a better fit if
- The list of available bindings is sufficient to meet the
requirements,
- The logging and troubleshooting capabilities are sufficient, and
you can build your custom monitoring tools,
- You require them to run not only on Azure, but on Azure Stack or
Containers, and
- You prefer to have all the power and flexibility of a robust programming
language.
It’s also worth mentioning that in most cases, the
operation costs of Logic Apps tend be higher than those of Durable Functions,
but that would depend case by case. And for enterprise-grade solutions, you
should not decide on a platform based on price only, but you have to consider
all the requirements and the value provided by the platform.
Having said all this, you can always mix and match
Logic Apps and Azure Functions in the same solution so you can get the best of
both worlds. Hopefully this post has given you enough information to
better choose the platform for your next cloud solution.
Happy clouding!
Commentaires