In this article, I would like to talk about serverless architecture in the scope of Microsoft Azure components. I assume that you have a basic understanding of what problems serverless is trying to solve. And what issues and complexities it introduces. If not, I would recommend reading my previous article.
 
The current Azure ecosystem distinguishes 6 core elements. They allow us to build serverless systems. At the very core, there would have to be the stateless functions. They perform actions or orchestration of actions to fulfil the business processes. Azure Functions come in pair with a set of Bindings. They come in the form of Attributes or config entries. We use bindings to describe an input or/and an output connection between our function and for example some event or datastore collection. But more on this later.
 
Then comes events which carry information between different components of our system followed by very important triggers and bindings. Triggers are the predefined actions that we will invoke as per their configuration on many different Azure Components. Right now we will talk about the cosmos database triggers, these fire on every change made to the CosmosDB (the preferred database for all things serverless in Azure). Another component worth mentioning is the Logic App which is a container for our functions but more on this bellow where we go a little deeper into each of these:

Functions

The blunt truth about them? They are cheap, and I mean dirt cheap. This is one of the core goals of serverless. To limit operational costs. Azure functions are a key component for achieving this. It’s best to check updated pricing here. But as of the writing of this article, you get 1 million requests and 400 000 GB of resource consumption per month for free. In the premium plan, you pay a little over 16 euro CENTS per million executions!
 
However, it’s not all sunshine and rainbows. There are some limitations, but there are ways to overcome them. One of these limitations is the maximum duration of a function. Generally, you should code your solution in such a way that it’s fast (aim for under a second execution). If there is something your function has to wait for, as an external API, you can use async-await keywords which will remember the local state of variables up to a point of await keyword. Next, the runtime will offload your function execution context until a signal is received from the external API at which point it will spin up a new context for your function and continue where it has left off. In the azure ecosystem, functions can be triggered by a lot of different things via build-in or custom build bindings.
 

Triggers

They are baked into the serverless architecture. Since functions do not even get instantiated until there is something to do – they do not expose any endpoints we can reach them at. Instead, a concept of a trigger exists and is supported by many of existing azure components like databases, event hubs and WebHooks. One of many scenarios you could configure with them could be: setting up a WebHook trigger, so that whenever we call some URL – our function gets instantiated and serve the request according to our logic. They can also be defined declaratively by decorating function with an attribute like so:
 
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]
 
or by adding an entry in .json config like this:

"bindings":[  
   {  
      "name":"order",
      "type":"queueTrigger",
      "direction":"in",
      "queueName":"%input-queue-name%",
      "connection":"MY_STORAGE_ACCT_APP_SETTING"
   }
]

 
Another example could be a queue trigger (as configured in above JSON). I know it’s in a section called “bindings” – so now is a good time to mention that triggers are a subset of bindings, they are the input bindings.

Bindings

Bindings are a way to pass the result of a functions work to some external component like an event grid or a database collection. We configure a binding for a function the same as a trigger so either declaratively or by config entry. Again – plenty of integration scenarios exist due to the wide support for standardized bindings in the Azure ecosystem.
 
I can imagine a scenario where a Function has an output binding for a SendGrid service that allows it to send email notifications whenever it is triggered. You can also create custom triggers and bindings to include whatever kind of parsing and validation you wish. You need a WCF SOAP style integration point? Not a problem, it’s all extendable. You can read more about bindings and triggers here.

Database

‘Azure Cosmos DB is Microsoft’s globally distributed, horizontally partitioned, multi-model database service.’ That’s a mouthful! Let’s try to break it down.
 
Global distribution and horizontal partitioning are features that gave CosmosDB another nickname, Planet-Scale database. That means (theoretically) no scaling limitations. Multimodel means that you can query it in various ways including query models based on DocumentDB SQL, MongoDB, Azure Table Storage, and Gremlin graph query API.
 
Another relevant fact worth mentioning is that Cosmos is not exactly new. The work on it began 14 years ago by some real cleaver people including the Turing Award Winner Dr Leslie Lamport. Cosmos is now production-ready. It has the full support of Microsoft SLAs. And what is most important for us in the scope of Serverless architecture – it supports triggers. Writes to CosmosDB can trigger azure Functions, Events and many more azure components, making it a perfect serverless ready database.
 

Events

The Azure ecosystem supports many technologies aiding messaging. But due to its unique capabilities Event Grid seems like the best choice for serverless applications (you are by no means limited to it). Event Grid is cheap (again a desirable feature in serverless architecture – you pay per event), it is also dynamically scalable efficient and reliable – support for dead-lettering exists. Some of its capabilities include:
  • Simplicity – Point and click to aim events from your Azure resource to any event handler or endpoint.
  • Advanced filtering – Filter on event type or event publish path to make sure event handlers only receive relevant events.
  • Fan-out – Subscribe several endpoints to the same event to send copies of the event to as many places as needed.
  • Reliability – 24-hour retry with exponential backoff to make sure events are delivered.
  • Pay-per-event – Pay only for the amount you use Event Grid.
  • High throughput – Build high-volume workloads on Event Grid with support for millions of events per second.
  • Built-in Events – Get up and running quickly with resource-defined built-in events.
  • Custom Events – Use Event Grid route, filter, and reliably deliver custom events in your app.

Logic Apps

In a nutshell, Logic Apps are configurable workflows – they use a concept of connectors (of which there are currently over 200) to integrate different azure and non-azure components including all the above-mentioned components. Logic Apps can help orchestrate steps of your business processes. Connectors can be thought of as smart configurable pipes able to achieve some complex tasks. To name a few, here are some connectors that can show you the range of possible integration:
  • SQL Server / Oracle Connector
  • SMTP / FTP Connector
  • XSLT Transformation Connector
  • Azure Machine Learning Connector
  • Office 365 Connector
 
If the list of over 200 existing connectors isn’t enough, you can always create a custom one. So as you can see Logic Apps are a perfect candidate for not only integration logic (which was its primary purpose) but also for a backbone of serverless application passing information between functions/events and the outside world.
 
 
Now that you know core components of Azure serverless offer I recommend you analyse a real live application like the one here. Or wait for an upcoming series of articles in which I will be describing building one from scratches! As always I hope you have found this useful and I encourage you to leave your thoughts/feedback in the comments below.

Software developer at Aspire Systems Poland. Problem solver. The more complicated the problem is, the more motivated he gets. Whether it’s designing, improving processes, architecture or coding, he will be the first one to jump right in.