Over the last few years, serverless functions (sometimes also referred to as “serverless” or “serverless computing”) has become a popular technology. However, there’s still a lot of confusion around the term. How can you run code without servers? What are the pros and cons of the technology? What are the situations where you might use it? In this article, I hope answer these questions and give you a good overview of the technology.
What are Serverless Functions?
The term “serverless” is sure to provoke curiosity the first time you hear it. “How do you run code on the web without a server?” you might wonder. What it actually means is that you, as a developer, don’t have to worry about the servers your code runs on. Provisioning of hardware, configuring networking, installing software, and scaling are all abstracted away by the serverless provider.
From a development perspective, a serverless function is a bundle of code that you upload to a serverless provider (such as AWS or Google). This code can be configured to respond to requests via a URL, run on a schedule (that is, via a cron job), or called from other services or serverless functions.
Serverless functions are ideal for adding a dash of backend functionality to frontend applications without the complexity and cost of running a full server.
At the other end of the scale, you can also build whole applications with serverless functions. In conjunction with other cloud services providing file storage, database systems, and authentication, it’s possible to build large, robust and scalable applications without having to provision a single server.
Serverless functions are run in micro-containers that are started up on demand. They’re designed for fairly short-running processes, and so billing is set with this in mind. Unlike full server instances, which are often billed by the hour, serverless functions are typically billed by the GB-second. With minimum billing durations in the order of milliseconds, low-frequency or sporadic workloads are much cheaper to run as serverless functions than traditional server instances. Light workloads and prototyping can even fall within the free tier of some providers.
The on-demand invocation of serverless functions means they scale quickly and easily with no extra work on the part of the developer. This makes them ideal for situations where traffic may spike unpredictably, as more instances of the function will automatically be made available to handle the load. The function will be scaled back down afterward, meaning you won’t be paying for unused capacity.
A key advantage to the serverless model is not having to deal with servers. Running a web application requires a lot of time and expertise in server administration in order to keep the software up to date with the latest security patches, and ensure that the server is correctly configured in order to be secure and performant. For start-ups and small businesses, hiring someone to deal with server administration is a large additional overhead. With serverless, developers can focus on creating solutions.
Of course, no technology is perfect, and serverless functions aren’t without their drawbacks. As I mentioned earlier, the serverless model is designed with short-lived processes in mind. With the maximum execution time measured in minutes (for example, 15 on AWS and 9 on Google), it’s not suitable for longer-running jobs like processing large batches of data.
Another widely discussed issue is that of the cold-start time. This is the time taken for the provider to provision and initialize a container for your serverless function before it’s ready to start running. Once a function has finished running, the container is kept around for a short time to be reused if the code is executed again. This “cold-start” delay could add between half a second to a second’s delay to your function’s response time. There are work-arounds for this, including the Serverless framework’s WarmUp plugin, which pings your function on a schedule to keep the container alive.
Although serverless functions free you up from having to worry about server provisioning and maintenance, that’s not to say there isn’t a learning curve. Building applications with serverless requires a different mindset to working with traditional monolithic codebases. You have to structure your code in a different way, breaking down the functionality into smaller, discrete services that fit within the constraints of the serverless functions. Deployment is also more complex, as each function is independently versioned and updated.
There’s also the issue of vendor lock-in that’s sometimes mentioned as a downside to serverless tech. As it currently stands, the major providers in this space (AWS, Google, Azure) have their own different implementations and management tools. This can make it difficult to move a serverless application from one cloud provider to another. Projects such as the Serverless Framework have attempted to abstract away the underlying services in order to make applications portable between providers.
Although serverless functions can be used to build entire applications, let’s take a look at some less ambitious use cases where serverless can benefit the average developer.
It’s not uncommon to have websites that are completely static, apart from a contact form that the client wants to be emailed to them when the user hits send. The site’s hosting provider may or may not support server-side scripting, and even then it may not be in a language you’re familiar with. Setting up a serverless function as a form mailer allows you to add the functionality to sites that are on static hosting.
Sometimes you may need a scheduled task to be run in the background. Normally, you’d have to pay for a server in order to set up a cron job, and this server would sit idle in between jobs. With a serverless function, you’ll only pay for the time the job spends running (and perhaps not at all, if it falls within the free tier).
Imagine that your React application allows the user to upload a photo to be used as an avatar throughout the app. You want to resize the uploaded image so you’re not wasting bandwidth by serving images that are far larger than needed. A serverless function could be used process the upload request, resizing the image to the required sizes and saving to a service such as S3 or Google Storage.
A Practical Example
In order to get a more hands-on understanding of working with serverless functions, let’s walk through a real-world example. We’ll create a static page with a newsletter signup form, that uses a serverless function to save the user’s name and email address to a Google spreadsheet.
1. Sign up for a Netlify account
We’re going to use Netlify as the host for this example, as they provide a free tier that includes serverless functions, and it’s very easy to get up and running. Firstly, pop over to their site and sign up for a free account.
2. Install the Netlify CLI tool
In order to test our example site locally and deploy to Netlify, we’re going to make use of their CLI tool. This can be installed as a global npm module from the command line:
npm install -g netlify-cli
Once the CLI is installed, running the following command will open a browser window to connect the CLI to your account:
3. Create a project folder and install dependencies
Let’s create a folder for the project, and initialize a new npm project:
mkdir serverless-mailinglist && cd serverless-mailinglist npm init -y
This will set us up with a
package.json file for the project, ready to install dependencies. Speaking of which, we’re going to need a couple of packages for our serverless function:
npm install dotenv google-spreadsheet
The first, dotenv, is a package that will allow us to load values from a
.env file in the root of our project and expose them to a Node script (our serverless function) as if they were environment variables. The other is google-spreadsheet, a package that wraps the Google Sheets API and makes it easier to work with.
4. Enable the Google Sheets API and create credentials
In order to use the Sheets API, we need to do a bit of prep work. First, you’ll need to enable the API for your Google account by heading over to the API console. Create a new project from the menu across the top, and then click the Enable button.
Once that’s done, you’ll need to create a Service Account. This account will give you a set of credentials with the necessary permissions to access the API. To do this, follow these steps:
- Make sure you’re on the Sheets API management screen.
- Click Credentials in the left sidebar, then click + CREATE CREDENTIALS and choose Service account from the drop-down.
- Fill out the form, choosing a name for the service account. The name you choose, plus the project name, will form part of the service account ID. For example, if you name the account “Mailing List” and the project name is “Sitepoint Serverless Demo”, the ID would be something like
firstname.lastname@example.org. Click CREATE.
- You can skip the remaining two optional sections on the page. Click CONTINUE and then DONE.
- Next, click on the newly created service account. This should take you to a screen showing the account details. Click KEYS in the top menu, then Add Key and Create new key. Choose JSON as the key type.
- Click the CREATE button and a JSON key file will be downloaded to your computer. (Note: this is the only copy, so keep it safe!)
A Guide to Serverless Functions and How to Deploy Them