Serverless is only for a CRUD scenario. Isn’t it?

Dariusz Parzygnat
Dec 13, 2019 · 5 min read

Many articles have been written about starting with FaaS and most of them create the impression that the functions must be simple and that they have to comply with a single responsibility principle.

Image: Pixabay

However, the business is never that simple. There are many workflows that describe each business domain and most are complex and an event at the beginning can influence a process at the end of a workflow. Does it mean that serverless isn’t suitable for such a situation? Should we only use it with CRUD scenarios?

Exemplary scenario

Let’s imagine this situation: ordering a product. After the request is saved, it’s required to prepare an invoice for a customer.

One function to rule them all

The simplest approach is to create one function that will do all the required stuff. So, the function is invoked by HttpRequest with an order. After validation, the order is saved to a database, e.g. Azure Table Storage. Then, the function generates an invoice and saves it to storage e.g. Azure Blob Storage. In the end, the function sends a status code to a caller (fig. 1).

Fig. 1 One function is responsible for processing an order and generating an invoice

A great advantage of the solution is simplicity. The entire logic is closed into one function and it handles exceptions easily. Moreover, we, as software developers, are accustomed to monoliths, so such an approach is more understandable.

On the other hand, the function breaks the single responsibility principle. The solution has many dependencies and after applying retry policies, the code can be complex and hard to understand. Furthermore, the caller has to wait for a response until the execution is finished. Preparing an invoice can be time-consuming, which means that a response will be provided after a few seconds. We have to remember that the function execution time is limited and packing a lot of dependencies can cause it to exceed its limits.

This function is to damn big

We decided that SRP is important and we want to apply it to the current solution. The function has two main dependencies: saving an order to a table and preparing an invoice for a customer. Let’s create two functions triggered by HTTP requests. The first function contains an order validation and saves it to a table. The second one creates an invoice and saves to blob storage (fig. 2).

Fig. 2 Split responsibility between two functions

Currently, the function is free of breaking SRP problems. Each function is responsible for one thing. The functions are simple, so the code would be easy to understand. Moreover, the approach complies with execution time limits.

Unfortunately, we still have a problem with a caller that waits a few seconds for a response. Even though it’s not such a big deal, it can be expensive. The first function is waiting for the second one’s outcome. If we used a standard approach with servers that are always on, it would be fine. However, it is an antipattern in the serverless world. The functions are currently highly coupled and we pay twice as much because the idle time of the first function is treated as execution time (fig. 3).

Fig. 3 Double paying caused by sync invoking of the second function

Why so synchronous?

As we can see, the current solution is too synchronous. We don’t want to make a customer wait for a response, because an invoice can be provided later. Let’s change a little bit of the previous solution: the second function is triggered by a message from a queue. It means that the first function adds a message to a queue, e.g. Azure Queue Storage, instead of making an HTTP request (fig. 4). Now, the function returns a response to a caller immediately. Furthermore, we don’t have to pay twice for execution, because the first function doesn’t wait for an outcome from the second one.

Fig. 4 Functions without sync dependency

Nevertheless, we lost the possibility to return information to a caller about an invoice. How can we inform him that something went wrong with the second function? Secondly, we should implement a dead letter queue service. The solution is more complicated and hard to understand for newcomers. Moreover, can we implement retry policy and exceptions handling easily?

Well, now we know what not to do

In Azure, there is a framework called Durable Functions that allows us to create processing workflows (more in post First face-off: Azure Durable Functions). Let’s try to use it. We need four functions now. The first one triggered by an HTTP request starts an orchestration. The second one describes the orchestration. It invokes that an order should be saved to a table (using the third function). Secondly, it delegates that an invoice should be generated and saved on storage (using the fourth function). Two more functions are responsible for executing the mentioned work.

Currently, the solution is simpler. Because the entire workflow is described in code, it is understandable for devs. Moreover, it complies with SRP rule and we don’t have to pay for idleness. Beyond that, inside the orchestrator function, it is possible to add retry policies and exceptions handling easily. Moreover, the framework can create and return a link to a processing status. And other than that, it is possible to provide output values, e.g. a link to a generated invoice. It allows a caller to request status and an invoice file location.

Summary

There are still many gaps in the serverless world. However, it doesn’t mean that it is only for demos and basic solutions. You just have to know when and how to use appropriate tools and concepts, just as we used Durable Functions in our solution. If you want to start with serverless, move your solution to serverless, or you need a review for your current architecture, together with ServerlessGuru, we will be glad to help you.

Dariusz Parzygnat

Founder — Serverless Wroclaw

LinkedIn — @dariuszparzygnat

Twitter — @dariusparzygnat

Thanks for reading 😃

If you would like to learn more about Serverless Guru, please follow us on Medium, Twitter, Instagram, Facebook, or LinkedIn!

Serverless Guru

Serverless guides on your cloud journey

Serverless Guru

Serverless Guru exists to be a change agent and overall guide to companies around the globe whom are moving to serverless at scale. We help companies understand where serverless fits and where it doesn’t. Then we lay a proven roadmap to move them along in their serverless journey

Dariusz Parzygnat

Written by

Serverless enthusiast, organizer of Serverless Wroclaw Meetup, “Serverless on platform Azure” book author

Serverless Guru

Serverless Guru exists to be a change agent and overall guide to companies around the globe whom are moving to serverless at scale. We help companies understand where serverless fits and where it doesn’t. Then we lay a proven roadmap to move them along in their serverless journey

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store