Skip to main content

Should I use Logic Apps or Azure Functions?

There are multiple ways to resolve the same business problems using Azure Services. Numerous times I was involved in a discussion where Azure Logic Apps and Azure Functions were put side by side.
In this post I would like to build another perspective of these two Azure services and when we shall use one or another, taking into account our functional needs and expectations.
Service Overview
Azure Logic Apps allows us to build workflows that are runnings as a service inside Azure, that can scale automatically and can be integrated with a high number of services from Azure or on-premises systems.
Azure Functions are the serverless offer from Microsoft that are highly scalable, well integrated and ready to respond to our future need.
Why is it hard to decide?
A part of the functionality offered by these two services overlaps or are similar. Decided on what business scenarios we shall use one or another it is not easy. Besides this, both services are so well integrated, that you have the feeling that you don't know which one shall integrate the other one.

1. Pricing
The price model for both of them is similar. Most of the costs are coming from the computation side, where you pay per usage and number of triggers. Both services can be hosted inside a dedicated App Services environment together with other services that you might have.
Inside Logic App, when you want to use Integration Account, an additional fee needs to be paid every month (fixed price/month).

2. Security
The Logic Apps can be accessed over HTTP triggers using a Shared Access Signature (SAS) similar to the one that we are using for Azure Storage., generated on top of the secret key, that can also be regenerated. There are other security layers supported by IP restrictions. In most of the cases, API Management is put in front of the Logic Apps to manage the security access and provide a stable API.
The Azure Functions are based on API keys, that can be defined at Azure Function instance level or per each function, depending on our needs. Additional security layers can be added using API Management or using a simple Azure Functions Proxies, that is more simple than API Management but can provide us with the right security functionality for HTTP triggers. When we host them in inside dedicated App Services env. We can add AD, Facebook, Google or other providers without code change, using the functionality that already exists inside App Services.

3. Networking
Except for the default consumption plans, Azure Functions are well integrated with VNETs. It enables us to integrated them with our existing on-premises (Site-to-Site VPN or ExpressRoute) or Azure infrastructure and to avoid to expose public endpoints - hybrid connectivity.
Logic Apps have a particular functionality to integration point for on-premises endpoints using On-premises Data Gateway. The solution needs to be installed on-premises and connect directly to our Logic App instance. There is no magic behind the scene; the gateway is using Azure Service Bus Relay to provide the secure tunnel between our on-premises system and Logic Apps.

4. Error management
Because Azure Functions are just a place where we run our code, there is no specific functionality for it. As for a typical application, we need to manage the exceptions and error by yourself. Retry mechanism needs to be integrated by yourself. Both retries and exceptions handling mechanism can be differed based on the language that we are using.
Azure Logic Apps are more user/develop friendly and provide us with support for exception handling that can catch the error and log it. There is an automatic retry mechanism can be used customised based on our needs. The retry mechanism is not perfect, and there are situations when human intervention is required to continue the flow after an error. This is caused because Logic Apps are workflows with a state.

5. Stateful (State)
Logics Apps are stateful by design. It goes hand in hand with workflow support and with excellent web and Visual Studio interface that allows the user to define the flow.
Azure Functions are a serverless approach for computation, and by design they are serverless. Using Durable function approach we have a framework that enables us to have business flows inside Azure Functions that have an internal state. This framework will allow us to run multiple functions in parallel and have long running functions. The state is stored inside Azure Storage and sometimes can create confusion and buggy code, but a strong development team can handle and resolve these issues. 

6. Developer perspective
Inside Azure Functions, we need to do all by code. There is no drag and drop support. Multiple programming languages are supported and more flexibility to the developer. In contrast, Logic Apps can be defined using a friendly interface where we can connect to external services, implement business logic and many more. You can define a Logic App without running a line of code. This feature is powerful, but in complex business scenarios, this can be tricky to manage.

7. External Connectivity
Azure Functions are built around the concept of output and input bindings and triggers. Most of Azure Services can be integrated directly with Azure Functions and all the time HTTP binding and triggered can be used to integrated provides that are not supported by default.
In contrast, Logic Apps are well integrated with a high number of applications and systems using connectors. There are not only cloud connectors, but also a high number of on-premises connectors, making Logic Apps appealing for enterprises that don't want to implement custom connectors. Connectors are designed smartly by storing the credentials and connectivity information inside them. Another cool feature is the possibility to reuse the same connector to multiple Logic Apps - define one and reuses as much as possible.

8. CI/CD and Deployment
Initially, the integration of Logic Apps with Azure DevOps and ARM was not the best - or better say it was almost none. A lot of things changed from then, and now both services are well integrated inside Azure DevOps. The automation and deployment part can be done using ARM template.
The most notable difference between them is the support of slots that it is available only for Azure Functions. This allows us to do fast switches between different versions of our functions. Even so, if you put an API Management in front of Logic Apps or use parallel instances of Logic Apps for different versions, you might not feel the lack of slots.

9. Cloud / On-premises environment
The current runtime of Logic Apps can be run only from Azure. You can use a dedicated environment inside App Services, but you cannot run them on-premises. This might change in the future, but for now, you are restricted to run them only from Azure.
Azure Functions are different from this perspective. The runtime supports different environments including Azure Stack. A more exotic location where you can run them is Windows Containers, where you would need an SQL Server for storage. This enables us to design a serverless solution that could run inside other cloud providers, like AWS or Google Cloud.

10. Maintenance
When you need to monitor Azure Functions, your first option is Application Insights from where you can fully monitor your functions (latency, status, errors and many more). There is also a dedicated tab inside the portal where you can find metrics about your functions and excellent integration with logging mechanism.
The Logic Apps provide us with historical information of previous runs from the same dashboard from where we define the workflows. This is super useful for business people that don't have technical knowledge. Each action from the workflow provides information related to what was the input, output and execution status. There is no integration with Application Insights, but it is well integrated with Azure Operation Mangement Suite (OMS).

The below tables compare both services from 6 different perspectives. 
Logic App
Azure Functions
Azure Portal / OMS
Azure Portal / Application Insights
Imperative (code-first)
Collections of actions
Separate actions that can call each other
High no. of connectors (including on-premises)
Basic bindings and extensibility using HTTP
Azure Portal / PowerShell / VS / REST API
Azure Portal / REST API / Visual Studio
Running environment
Azure only
Azure / locally / other clouds

Final conclusion
Logic apps are suited when you develop integration solutions (strong connectors) that reduce the time to market and has a rich visual tool that can be used to build and manage the workflows. Suitable for business process automation where reliable processing is mandatory.  
Azure Functions together with Durable Functions are more flexible and the technical team has full control and power. They are more powerful and portable. Can be used with success for complex logic when you have more than a few IFs conditions.   

Azure Functions:
  • Code triggered by an event
  • Runs on different environments, including local workstations
  • Synchronous request/response calls
  • Complex logic
Logic Apps are:
  • Workflows triggered by an event
  • Runs only in code
  • Asynchronous integration
  • Fire and forget where reliable processing is mandatory 
  • Business process automation
  • Well integrated with on-premises systems 


Popular posts from this blog

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine:
threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration:

TeamCity.NET 4.51EF 6.0.2VS2013
It seems that there …

Entity Framework (EF) TransactionScope vs Database.BeginTransaction

In today blog post we will talk a little about a new feature that is available on EF6+ related to Transactions.
Until now, when we had to use transaction we used ‘TransactionScope’. It works great and I would say that is something that is now in our blood.
using (var scope = new TransactionScope(TransactionScopeOption.Required)) { using (SqlConnection conn = new SqlConnection("...")) { conn.Open(); SqlCommand sqlCommand = new SqlCommand(); sqlCommand.Connection = conn; sqlCommand.CommandText = ... sqlCommand.ExecuteNonQuery(); ... } scope.Complete(); } Starting with EF6.0 we have a new way to work with transactions. The new approach is based on Database.BeginTransaction(), Database.Rollback(), Database.Commit(). Yes, no more TransactionScope.
In the followi…

GET call of REST API that contains '/'-slash character in the value of a parameter

Let’s assume that we have the following scenario: I have a public HTTP endpoint and I need to post some content using GET command. One of the parameters contains special characters like “\” and “/”. If the endpoint is an ApiController than you may have problems if you encode the parameter using the http encoder.
using (var httpClient = new HttpClient()) { httpClient.BaseAddress = baseUrl; Task<HttpResponseMessage> response = httpClient.GetAsync(string.Format("api/foo/{0}", "qwert/qwerqwer"))); response.Wait(); response.Result.EnsureSuccessStatusCode(); } One possible solution would be to encode the query parameter using UrlTokenEncode method of HttpServerUtility class and GetBytes method ofUTF8. In this way you would get the array of bytes of the parameter and encode them as a url token.
The following code show to you how you could write the encode and decode methods.