This article is part of #ServerlessSeptember. You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles are published every day — that's right, every day — from community members and cloud advocates in the month of September.
.NET has been the go-to platform for building enterprise and line-of-business applications for as long as I can remember. In the past, there's been a tendency for these types of applications to lag behind in terms of technology adoption. That's starting to change, in large part from the benefits of managed cloud services like Azure SQL, Azure AD, and today's topic, serverless, or more precisely Azure Functions and Logic Apps.
Line-of-business applications are needed to run a company's day to day activities. These apps may only exist within the enterprise, but that doesn't mean that they can't leverage the power of cloud computing. Serverless, and Functions in particular, is a logical way to extend a LOB application that is struggling to keep up with today's trends.
Below I've outlined a few ways that Azure's serverless stack lets you try new ways of doing things, simplify your day-to-day work, and make new programming tasks easier.
Most software development teams have a specific tech stack that they work with. Lots of work is put in to developing the right practices, tooling, and infrastructure to support a given technology stack, so it's not something you can change on a dime. As the saying goes, when all you've got is a hammer, every problem has to look like a nail.
Functions give you the opportunity to leverage the strengths of more languages, without having to be an expert in building, deploying, running, and monitoring its technology stack. Of course, you'll need to learn the basics of the language, but that's the fun part.
When it comes to Continuous Integration and Deployment, Azure DevOps has you covered with custom tasks and templates for its supported languages. The operational aspects of running Functions are kept out of your control as well, leaving you to focus entirely on the code.
Debugging production issues is a breeze when you enable Application Insights. It provides you with the feedback you need to figure out what's going wrong with your code, without affecting performance. Every step of the way, the guesswork is taken out of the equation.
Building a small feature with functions isn't much of a risk at all since you can be up and running in a matter of hours. They provide you with a safe space to experiment, so the next time you think a task could be done better some other way, think about Azure Functions.
Logic Apps are the second arm of serverless in Azure. Both Functions and Logic Apps are event-based, triggered when an event occurs within Azure. But Logic Apps can be triggered by much more than just Azure services.
They can connect to services that are frequently used in the enterprise, like Office365, Dynamics, SharePoint, SalesForce, and more. For that reason, Logic Apps are incredibly useful to tie together radically different data sources which you can't easily access otherwise.
Logic Apps are created through a designer that's available in the portal or as an extension in Visual Studio. You start by specifying the event that triggers the execution of the Logic App; say whenever a SharePoint document is created. Then, you tell it what to do with the related event data. Perhaps it's to send an email, or write a record to a database. You can add conditionals, loops, and pretty much anything you'd expect from a basic programming language.
The more steps you add, the bigger the Logic App becomes. The designer does its best to keep things tidy, but a Logic App with many steps can quickly become unwieldy. That's where having a function work alongside the Logic App helps to keep things under control.
As a developer, it's only natural to feel more comfortable writing code rather than designing a workflow, even if it is in Visual Studio. But Functions alone can't connect to anywhere near the number of data sources that Logic Apps can. One approach that I like to use combines them both:
- Create a Logic App that is triggered by the data source event that you're interested in.
- The Logic App fires when the event occurs. All the data related to the event is available within the workflow.
- The Logic App then invokes an HTTP Trigger function, passing along the relevant event data in the message body.
- The function, written in your language of choice, receives the event data and does whatever needs to be done.
- If needed, you can invoke more than one function in the workflow, passing data from one to the other.
There are a few advantages to doing things this way. Obviously, the Logic App process stays small, so it's easy to follow along. The majority of the business logic is written in code, so it's easy to understand as well.
More interestingly, this approach lets you visualize the entire process from start to finish within the Logic App. At a glance, you can see where the process failed, and take action as required.
There are many scenarios like this where combining a Logic App with Functions makes for a more maintainable solution than using either one separately. Leveraging them together makes for seamless interactions between systems.
In an ideal world, the applications we write run like clockwork, with no undesirable side effects caused by bugs. Reality is somewhat different. More frequently than you or I would like to admit, manual operations need to be executed to quickly address some unforeseen scenario that's crashing production. It's especially the case of older line-of-business applications that can't be quickly hotfixed, since they aren't backed by a Continuous Deployment pipeline.
Functions are a great way to address those issues when they crop up, and keep an eye on the goings on within your application. Need to verify that a business event was completed before a certain time? You can write a Timer Trigger function that does just that. Want to perform an action when a certain event occurs? You can write an Event Hub Trigger that listens to that event. The sky's the limit when it comes to these types of interactions.
From a DevOps perspective, HTTP trigger functions open up a whole slew of possibilities. A line-of-business application rarely has a cookie-cutter release process. There could be state that needs to be reset, build definitions that need to be incremented, stale branches that need to be cleaned up, and who knows what else that needs to happen when the software is released. So long as your CI/CD tools support webhooks, you're all set with an HTTP Trigger function.
The best thing about automating with functions is the traceability that they provide. Each function is coded, tested, and deployed just like any other code. On top of that, every execution is logged by Application Insights, so there's never any doubt as to what did or didn't run. Nothing is left to chance.
Even line of business apps eventually come to end of life. When they do, it's usually because the business model has changed so drastically that a massive change in direction is needed.
Building a new application from scratch can be risky, so it's a good idea to first build a proof of concept to test the ideas, assumptions and biases of product management and developers alike. From a technical perspective, it's an opportunity to try new technologies that can help you deliver faster without compromising on scalability, reliability, and quality.
Those requirements make Azure Functions, and more generally serverless, the perfect platform from which to build a proof of concept. You already know that functions are great for reacting to events in Azure. But rather than building an HTTP API with ASP.NET Core, have a look at how much you can do with HTTP Trigger functions and API Management. The feature set is rich enough to build a full-blown application, let alone a proof of concept.
Similarly, functions are perfect for building any type of asynchronous background worker. With next to no configuration, you can be dequeuing messages from Storage Queues and Service Bus to perform whatever processing is needed. Writing the equivalent Worker Service or Console application is bound to be much more time consuming.
From an operations perspective, you don't need to spend endless hours learning how to properly manage the runtime environment. It's entirely taken care of, so you can focus on writing code, not managing infrastructure.
On top of that, Function's cost model means that if your POC isn't used at all, it won't cost a cent. And if traffic goes through the roof, you won't be scrambling to bring up extra resources to keep up with demand, because functions scale up and down automatically based on load.
Before you know it, the POC will turn into an MVP, and the MVP into a complete application running in production.
There are many ways that Functions can help you be a better enterprise developer. Whether you're building the next iteration of your line of business application, automating day-to-day tasks, integrating with different data sources or just experimenting to see what's possible, you can't really go wrong with Functions. It's a modern and flexible platform that can take the hits and keep on trucking.
You can learn all you need to know about developing with Azure Functions by reading my development guide.
Find out more about how Microsoft Azure enables your Serverless functions at https://docs.microsoft.com/azure/azure-functions/.