The word ‘Serverless’ is popping up various articles and blogs on Platform services like Logic Apps and Azure Functions. Both these services have unique requirements, therefore comparing Logic Apps and Azure Functions is important. In a previous blog – Serverless Computing: why should I consider using it? on Serverless360 blog, serverless is very well explained and both Logic Apps and Azure Functions are Platform Services, and you could even consider them serverless – no infrastructure to manage (done for you by Microsoft), auto-scaling, or billing per execution or action. If you look at one of the diagrams Microsoft shows in their presentations – you will notice both Logic App and Azure Function are a part of Azure Application or Serverless Platform.
You can leverage both Logic Apps and Azure Functions through a consumption plan. However, there are differences and depending on your requirements, you can either use Logic Apps, or Azure Functions, or both. In this blog post, we will briefly discuss both services before showing how to use both in a cloud-native integration scenario, comparing Logic Apps and Azure Functions, and when to use either one of them.
Free download this blog as a PDF document for offline read.
Azure Logic Apps
You can run a business workflow in Azure using the Logic App service. The Logic App is a logical container for one workflow you can define using triggers and actions. A trigger can instantiate a workflow, which can consist of one or many activities (actions). For instance, you can trigger a workflow by sending an HTTP request or schedule a workflow every hour to retrieve data from a public website.
A Logic App runs on the infrastructure of an Azure region (VM’s in a data centre), not visible to you as it is abstracted away. By provisioning a Logic App, you leverage a bit of that infrastructure (indirectly via the Logic App Service) once you define a workflow and the flow gets triggered. Furthermore, you get billed by some trigger/actions that execute, and scaling done for you – if let’s say the number of request increases, so will the Logic App instances until certain boundaries are reached (see Logic App Limitations).
The Logic App service runs as said earlier on a set of infrastructure, and it consists of several components.
These components are:
- Logic Apps RP – Reads the workflow definition and breaks down into a composition of tasks with dependencies.
- Logic Apps Runtime – Distributed compute/workers are coordinated to complete tasks on-demand.
- Connection Manager – Manages connection configuration, credentials, and token refreshment.
- Connector Runtime – API abstraction via Open API descriptions.
Azure Functions are part of the Azure Web + Mobile suite of App Services and are designed to enable the creation of small pieces of meaningful, reusable methods, easily shared across services. You can build the Azure Function in various languages like Node.js, C#, F#, Python, PHP, and even Java. Followed by scripting languages, Bash, and PowerShell – and support for Command Line through CMD- or BAT file. Although an Azure Function can contain quite a bit of code. They are typically designed to serve a single purpose and respond to events in connected services.
The WebJobs SDK runtime, a framework that simplifies the task of writing a background processing code that runs in Microsoft Azure, is the foundation of Azure Functions. Furthermore, Functions leverage a declarative binding and trigger mechanism, which works with several Azure services like Storage, Cosmos DB, and the Service Bus. Below you see a diagram of the components of Azure Functions.
For more information about Azure Functions read the Leveraging Functions on the Azure Platform blog post.
Comparing Logic Apps and Azure Functions
In the previous paragraphs, we explained both Logic Apps and Azure Functions. Now we will compare Logic Apps and Azure Functions, how both can work together. Also, when you should use Logic Apps or Azure Functions. The differences between Logic Apps and Azure Functions range from developer experience to deployments. In the following paragraphs, we will address them.
“Azure Functions is code being triggered by an event, whereas Logic Apps is a workflow triggered by an event.”
You can develop Logic Apps and Azure Functions in the browser and Visual Studio. The experience, however, is not the same – developing functions in Visual Studio are better than for Logic Apps – as the responsiveness of the workflow designer compared to the browser is slower. Furthermore, you generate code for a function, while you design workflow with Logic Apps. Moreover, you can view the latter as ‘no-code’ or ‘low-code’ development.
WithAzure Functions, you have more control and fewer limitations when you face complex scenarios or requirements as coding provides you with much flexibility, but also more responsibility. Logic Apps have predefined triggers (managed connectors) and actions. However, you can leverage variables, built-in expressions, or call-out to an API or Function (more later in working with Logic Apps and Azure Functions). Furthermore, you can build custom connectors for Logic Apps if the connector doesn’t exist. For functions, this will be harder if a binding is not available.
One of the fundamental concepts of Logic Apps is connectors – bringing connectivity to the workflow. The connectors provide a means to trigger a workflow and a payload into or out of the flow. Microsoft has built an extensive set of connectors ranging from Azure Service to popular SaaS solutions. Furthermore, Microsoft continues to invest in developing more and more connectors. In case a connector doesn’t exist you can build a connector yourself through the custom connector template in the Azure Marketplace.
Each connector you choose when defining a workflow comes with an API connection (connectors are a wrapper around an API and operations) and requires credentials stored securely. Once you have chosen a connector and done the authentication, you have what is called a managed API connection, which you will see in the resource group where your Logic App resides. Moreover, you can reuse these connections in other Logic Apps.
Azure Functions do not have connectors, yet rely on triggers and input and output bindings – like Storage, Event Hubs, Service Bus, and Cosmos DB. Bindings in Azure Functions provide a way to connect to data with code declaratively – you define them by specifying a connection string and other properties depending on the binding you choose. Furthermore, you can extend the bindings by leveraging the extensions available in the WebJob SDK. The list of bindings is limited compared to Logic Apps.
In the previous paragraph, we mentioned authentication for Logic App connectors and connection strings for Azure Function bindings. Every connector comes with its security depending on what API it exposes, for instance, the Dynamic 365 connector requires a Dynamics Account to be able to sign in to Dynamics 365. Or to access a Logic App via an HTTP endpoint, when you use the HTTP trigger for your workflow, the client must include a so-called Shared Access Signature in the URL – generated via a secret key that can be regenerated at all time. Furthermore, you can secure the Logic App by placing Azure API Management before it. See also Protecting Azure Logic Apps with Azure API Management on the BizTalk360 blog and Middleware Friday.
With Azure Functions the security is different – you can secure accessible, public functions (HTTP and WebHook Binding) with Authorization keys. These keys are generated when you create a function and can be regenerated. Furthermore, you can leverage authentication functionality through the general setting with Azure Active Directory, Google, Facebook, and others. On top of your HTTP/WebHook triggered functions you choose the lightweight Azure Functions proxies or API Management.
One of the essential aspects of both Logic Apps and Azure Function is the handling of exceptions. Handling exceptions in your Logic App or Function will make them more robust – the handling of exceptions does differ between Logic Apps and Azure Functions. Logic Apps exception handling is an out-of-the functionality with retries, scopes, and run after configurations, while Azure Functions you can apply the standard try-catch. In both cases you will have to do design and work to have it in place – it doesn’t come by itself. Note that with Azure Functions you do not have the out-of-the-box retry capability like Logic Apps except for Azure Queue and Blob Storage. For more details on error handling with Azure Functions see Azure Functions error handling.
Since the inception Azure Functions are stateless, accept data from input, processing it, and then handling appropriate actions, i.e. one or more outputs – the function acts as a single software switch. However, this has changed with the release of ‘durable functions’ or what Microsoft calls “orchestrator functions.” With Durable Functions, Microsoft provides state and long-running capabilities for Azure Functions, by leveraging the Durable Task Framework. Moreover, durable functions allow sequential and parallel execution of several Functions, support long-running tasks with pre-defined timeouts, and provides stateful actors without the need for external storage. The state is automatically stored in through the belonging Azure Storage account in Storage queues, tables, and blobs, which is disaster proof. These long-running and stateful processes are inherently available in Logic Apps, except for the stateful actor model.
The consumption model for Logic Apps and Azure Functions provide a specific auto-scale capability, i.e. when your load increases the Logic App or Function can scale with it to a certain point. Logic Apps can scale depending on the connector(s) you use, for instance, the File System connector current limit of 100 calls per minute.
Like Logic Apps, Azure Functions can run under a consumption plan – instances of the Azure Functions host are dynamically added and removed based on the number of incoming events. The plan supports the auto scale – read more about it through how consumption plan works. Besides a consumption plan, Azure Functions can also run under an App Service Plan, which means specifying the number of dedicated VM’s through a Basic, Standard, Premium, or Isolated SKU. Having an App Service Plan instead of a consumption plan depends on your requirements for more processing power that exceeds the consumption plan, or you need to support scenarios where for instance your function apps need to run continuously.
With deployments of resources in Azure, you can think of the Azure Resource Manager (ARM) templates. This also accounts for deploying Logic Apps and Azure Functions. Both have built-in support for these templates. You can automate the deployment of Logic App through the Azure Portal leveraging the automation script or by using Visual Studio.
With Azure Functions, you can quickly set up continuous deployments through triggers from sources like Bitbucket, Dropbox, Git, GitHub, OneDrive, and VSTS (see for example Leveraging Functions on the Azure Platform blog post). Additionally, Azure Functions have deployment slots in the preview, allowing deploying and testing a vNext first, before you swap the tested deployment slot with the current version in production.
Logic Apps provides a run-history feature enabling you to examine specific runs in full detail. Also, you can filter this history, based on a period and the resulting run status. Furthermore, Logic Apps integrates with Operation Management Suite (OMS) in Azure – for instance with one button click you can enable integration with OMS, where you can search for tracked properties.
With Azure Functions you have access to the monitor tab, here you can see the execution history. Besides that, there is a live event stream that shows the almost real-time processing statistics in graphs. Furthermore, there’s full integration with Application Insights, where you can take advantage of the powerful Analytics queries.
You can also leverage a third party solution like Serverless360 to monitor your Logic Apps and Azure Functions. Serverless360 offers even more capabilities than Azure Serverless monitoring – you can also operate and manage Logic Apps and Azure Functions. Serverless360 is built as a complement to Azure portal capabilities like Application Insights and Azure Monitor.
Every Logic App would have one or more trigger definitions which would be followed by a sequence of run actions that define the workflow. There could be scenarios where the trigger would have been successful but one of the run actions would have failed. This would break the workflow and immediate notification on the failure of the run action with details would be of great help to bring the workflow up. Similar would be the requirement to get notified on the failure of an invocation of Azure Function. Getting notified on the failure of Logic App run action and Azure function invocation in near real-time is now possible with Serverless360.
When comparing Logic Apps and Azure Functions, both can run under a consumption plan. That means both have a pay-per-usage billing model.
Azure Logic Apps
Price/Unit of Measure
Price per Execution:
Standard Connector €0.000106
Enterprise Connector €0.000844
Execution Time €0.000014/GB-s
Total Executions €0.169 per million execution
Consumption plan pricing includes a monthly free grant of 1 million requests and 400,000 GB-s of resource consumption per month.
Note: Azure Functions can also run under App Service Plan – hence a different pricing model.
In case you leverage the integration account with your Logic Apps than you should be aware of additional costs.
Working with Logic Apps and Functions
“Logic Apps love Azure Functions.”
A Logic App can call a Function, to perform for instance conversion of Euro to Dollars or vice versa. Assume you’re building Logic App that receives an order request via a public facing website selling items in local currency. Once the Logic App consumes the order request, it will need to create a consistent message for a back-end system including the currency set to USD. Currently, in Logic Apps, there are no expressions available to perform this type of conversion. Hence, you need to call a function, which performs the conversion for you.
The Logic App and Function work together to enrich a message with another currency as shown below:
The Function gets the latest exchange rates and converts the EURO amount to USD (internal currency). The Logic App picks up the message from the queue and passes on successful enrichment the message to another queue. On failure, the message ends up in the dead letter queue.
When to use Logic Apps
Logic Apps are “event-driven” meaning they run based on a trigger. That is an HTTP request, message on a queue, a blob created in a container, or schedule.
Typical scenarios for Logic Apps are:
- SaaS event processing
- Timer-based processing
- Data Ingestion (see for instance the following Middleware Friday episode)
- Business Process
- Integration between (Cloud) services
- Content-based routing
- Data transformation and enrichment
When to use Functions
Azure Functions like Logic Apps are “event-driven” meaning they run based on associated and configured events, or “triggers”. For example, an Azure Function could be triggered by a simple timer. Such as running a process once every 24-hours or triggered by an event in a document management system. Also, when a new document is uploaded to a SharePoint library. Azure Functions can also respond to Azure-specific events. Such as an image added to a Storage Blob or a notification arriving in a Message Queue.
Typical scenarios for Azure Functions are:
- Timer-based processing
- Azure service event processing
- SaaS event processing
- Serverless web application architectures
- Serverless mobile backends
- Real-time stream processing
- Real-time bot messaging
In this blog post, we discussed both Azure Logic Apps and Azure Functions, how they can collaborate on cloud-native integration scenarios, Logic Apps vs Azure Functions, and when to use them. Both Logic Apps and Azure Functions are ‘true PaaS’ or ‘Serverless’ and deliver value to your cloud-native solutions.