Building Applications for Serverless Architecture

“Serverless” technology can greatly simplify software development and deployment. Amazon’s AWS Lambda and Microsoft’s Azure Functions let developers deploy code without having to deal with provisioning and scaling. At the same time, they enjoy substantial cost savings.

Serverless, aka FaaS

The name “serverless” is a misnomer. The code runs on a server, of course. Some people prefer “functions as a service” or FaaS, which is more accurate. But “serverless” what most people are calling it, so we’re stuck with that name for now.

Whatever it’s called, it consists of an environment where the developer can deploy functions without dealing with the infrastructure. There’s no associated file system or persistent storage. Rather than having an application that’s always running, a serverless environment is completely inactive except when one of its functions is called.

In reality, a “serverless” environment is anything but that. Usually HTTP calls invoke the functions, so there’s an HTTP server providing access. The ability to invoke the code needs to be controlled, so there’s an authentication server. AWS Lambda and Azure Functions provide ways to invoke code through HTTP. Setting up a RESTful service is straightforward.

Serverless code can provide a backend to an application. It can provide a set of dedicated functions that do the work for a lightweight front end, or it can publish an API which any suitable application can invoke. In this scenario, it’s middleware between a front end, such as a mobile application, and a data store.

Reasons to Go Serverless (or Not)

A serverless environment provides two big advantages: economy and simplicity. It’s economical because the code isn’t always running. Customers pay only when the functions are invoked. This reduces the demand for system resources, since nothing is happening and nothing needs to be retained between calls.

It’s simple because each function call is an isolated occurrence. Any number of calls to a function can take place at the same time, and each one runs independently. This approach scales naturally.

The functions aren’t necessarily invoked by explicit calls from a front end. Amazon uses the word “triggering” rather than calling. They can be event-driven, running at regular time intervals or in response to an input.

Some use cases aren’t well suited for this kind of treatment. There is a time limit on each function invocation; Lambda, for example, limits each one to five minutes. A function that might run indefinitely won’t fit in this scheme.

Latency can be a problem. Each function invocation has to be set up, and that’s slower than calling a function within a running application. Each function needs to do a big enough piece of work to justify the overhead, but it has to respect the maximum time limit. The overhead in managing the application’s state may be significant, since it requires calling an outside service. Some type of temporary or cache storage may be available to the functions. It isn’t guaranteed to be there indefinitely, but using it can reduce the number of calls needed to maintain state. AWS Lambda provides Amazon Step Functions for state management without a lot of overhead.

Comparison with PaaS

With PaaS, the developer sets up an application which is always running. It has access to files and can hold information in memory as long as it’s active. It interacts with an operating environment, which could be a standard operating system or a vendor-specific layer on top of the OS.

This approach provides a lot of flexibility. The application can retain any information it needs and adjust its actions depending on its history. A running application has very little latency when it’s called, and keeping state information in main memory lets it respond quickly.

With power comes responsibility. The application has to be configured. Scaling is an issue; how many concurrent requests can an application handle? It’s possible to spawn additional instances when the workload grows, but the developer has to strike a balance between the burden an instance carries and the overhead of creating more instances.

A benefit of PaaS, compared to serverless code, is that the environment provides a buffer against vendor dependencies. A Linux distribution on one cloud environment is compatible with the same Linux distribution on a different cloud.

With serverless code, the situation is simpler. Each function invocation is separate, and there are no instances to deploy. Scaling happens automatically, without any need to configure it.

The downside is that there’s no global memory to get information from. Generally, serverless code will rely on a separate service to manage data. Environment variables give it the information for accessing the service.

Migrating code from one vendor to another may be difficult. Ironically, being “serverless” means dependency on the server. There’s nothing to isolate the code from the vendor’s own ways of deploying and invoking it.

Comparison with containerization

Containerized applications aim for improvements that are similar to serverless code. With a containerized environment such as Docker, it’s straightforward to deploy as many instances as necessary of an application and tear them down when they aren’t needed. However, it has the overhead of launching each instance, so the applications can’t be too fine-grained without losing efficiency.

Containerized applications deal with scaling better than traditional ones. However, they don’t relieve the administrator of the need to manage scaling parameters. On the positive side, they can be better suited to very heavy loads, since containers can be deployed over as many server instances as the service agreement allows. The maximum number of concurrent serverless calls may be subject to a hard limit.

Building an application with serverless code

A serverless application consists of some event-driven functions and usually a backend for handling data. The simplest “Hello World” application would be just one function and an event definition to trigger it. A Web page could invoke it and display the value it returned. With an API dispatcher and a database, an application can respond to a variety of requests.

How the functions are called depends on the vendor’s service. Usually the invocation is based on the HTTP protocol. Lambda functions are invoked by events, which the caller publishes. They can also be called using the API Gateway. Azure Functions are called by webhooks over HTTP.

Some applications can be open to anyone who finds their URL, but many need authentication so not just anyone can wander in from the Internet. An authentication layer stands between the functions and the Internet, controlling access.

“Serverless” may not really be serverless, but the range of applications that it can support is surprisingly broad. It’s worth exploring as an alternative to conventional cloud applications.