Serverless Computing

The introduction of cloud functions brought us serverless architecture models. Cloud functions of course still run on servers but these servers are invisible for function developers: they are provided as backend as a service.

Cloud platforms (AWS, Google Cloud, Microsoft Azure, etc.) take care of provisioning and managing the resources which are needed for the functions to run.

The creators of cloud functions only need to write the code and provide some configuration data. The rest is taken care of by the cloud platforms.

Triggers

Cloud functions only run in response to events that we want to act on. These events happen in the cloud environment of the function. Such events can be:

  • Incoming HTTP requests
  • Scheduled (cron) events
  • Incoming messages in streams (AWS Kinesis, Google Cloud Pub/Sub, etc.)
  • Data changing in databases (AWS DynamoDB, Google Cloud Firestore, etc.)
  • File operations in object stores (AWS S3, Google Cloud Storage, etc.).
  • Functions calling other functions

Execution environment

Cloud functions are executed in isolated containers. These containers are provided by the platform the developer has little influence on starting and stopping them.

When developers write the code for cloud functions they only have to concentrate on what payload their functions get as input and what outputs or side effects the functions should generate (e.g. returning the HTTP response, updating records in a database, uploadin files to cloud buckets).

The input payload usually differs based on what triggered the function. E.g. for HTTP triggered functions the input contains request headers, query parameters, the URL and similar things. For database events the input contains the record which was added, changed or deleted. For streams the payload contains the data that was pushed in the stream.

Besides these the input payload also contains some generic data, such as a timestamp.

Cold starts and warm containers

Before a cloud function can be executed many things need to happen: the platform needs to provision and start up the container for execution environment and the executable code needs to be loaded into the container and also some parts of the code need to be executed.

This always takes some time. How much? It depends on the size of the code bundle we want to run and also on how much setup our code does.

Typical start up times are way below 1 second.

Cloud platforms usually do not destroy containers right after executing a function. Containers are kept “warm” for a few minutes so that subsequent calls can be executed quicker and cheaper.

Scaling

The beauty of cloud functions is that they can scale up and down virtually without any limits. When a function gets invoked the platform creates a container instance which runs the function code which then processes the event. If a function gets invoked while one event is being processed the platform spins up a new container instance which again runs the code which processed the second event. And so on for even more concurrent events.

The upper limit for concurrent execution has only some practical limits but conceptually it can scale indefinitely.

Statelessness

Cloud computing platforms take care of managing the resources needed for running cloud functions. In order to allow cloud platforms to automatically scale functions they must be stateless. This means that they should not rely on previous function invokations. In other words they should not rely on building up state in memory. The underlying infrastructure can start and stop function containers any time. There is no guarantee that two consecutive calls are send to the same container.

Sync vs. async invokation

Cloud functions can be invoked in two modes: synchronously and asynchronously. In sync mode the caller (web browser, other function) waits for the response of the function. In async mode the caller just triggers the function but does not wait for any return value (fire and forget).

Configuration

The most important configuration data is the trigger type. When or in response to which event should the function be invoked (see triggers).

When a user creates a function they have to provide the amount of CPU and memory they want to allocate for each function call. The more memory or the more CPU power the higher the costs of the execution per time.

Besides CPU and memory the developers can also provide other configuration data in the form of environment variables. These then can be read by the function when the code gets executed.

Pricing model

Most cloud platform providers have very similar pricing models. Typically we pay for the time it takes to execute our functions and for the number of executions. The cost per second depends on how much memory and CPU is configured for a function. Most providers therefore define the costs in GB-sconds and GHz-seconds.

We also have to pay for other resources used by the cloud functions, such as databases, network, APIs (AI, translation, image recognition), etc.

Good things come in pairs

Most cloud functions do not only exist to execute some code and return the result like a calculator. Most cloud functions are paired with other services. Here are some possible use cases:

  • Get and validate data coming from an HTTP request and store the data into a database
  • When data is added or changed in a database the cloud function can save a backup copy into an object storage
  • The function receives some text through an HTTP call and then translates that text to a different language using some cloud translation service
  • The function receives an event from a stream, then filters and transforms these events and then stores the data in a cloud database

Further reading