An introduction to serverless architecture; we outline the pros and cons of using this setup for running applications and take you through an example serverless app. We’ll guide you through building your own serverless web service with Node.js so you can see just how efficient this technology really is.

Serverless architecture

A serverless architecture relies on third party backend services (usually PaaS solutions) and custom code ran in ephemeral containers. It allows us to run an application and necessary services without having to manage the infrastructure. In a container execution model, a provider dynamically manages the allocation of resources, so your application can scale automatically depending on the actual traffic, and pricing is based on the actual usage of the resources.

AWS Lambda and Firebase are the most well known serverless vendors. However, there is slight difference between the two: while AWS Lambda allows you to run your custom serverless applications code, Firebase provides database as service with hooks and functions that allows you to connect the database backend with additional services (push notifications, authentication, http triggers etc.). Firebase itself was acquired by Google in 2014 and is part of their larger set of cloud functions that run on their powerful infrastructure, which also provide integrations with Github, BitBucket, etc.

Pros and cons of the serverless approach

As with any software configuration approach, the pros and cons of using a different architecture are highly case dependent - with the good outweighing the bad and vice versa for different projects. It shows that, even though great in theory, serverless architecture has many caveats and should be approached with care. This is where we can come in and guide towards which is going to be the best approach for your setup. We are experts in the domain, plus offer serverless node.js developers to help you build, if severless comes out as a clever decision for your company. Here are just some of the pros and cons of going serverless:

Pros

  • Autoscaling - For instance, if you are using AWS Lambda, it rapidly launches as many copies of the function as needed to scale to the rate of incoming events.
  • Lower infrastructure costs - pay as you use, costs reflects the usage and scale of the application.
  • No infrastructure management - you don’t need to manage servers, databases, etc.
  • Ease of deployment - some frameworks, like Serverless, allow you to deploy (and to rollback) code to services with single command.
  • Reduced development cost - by using external services and SDKs for common tasks. For example, when using Firebase, we don’t need to build an API layer for the database, we can just configure the schema and access rules and then use it right away.

Cons

  • Potential vendor lock-in - an app may not be portable to a different provider without some modification.
  • Security concerns - with services like Firebase you are losing that middleware protective layer between your UI app and the database backend service.
  • Services limitations - AWS Lambda, for instance, has invocation limits that you won’t be able to overcome easily. At the moment Concurrent Execution Limit is 1000 and exceeding this number will result in errors and a general slow down. However it does allow us to use normal language and operating system features, such as creating additional threads and processes.
  • Warm-up time - on-demand services, like AWS Lambda, require a certain warm-up time before the first use; however this can be circumvented.
  • Testing - running integration or end to end tests is difficult because you rely on external infrastructure which is not reproducible on a local machine or CI servers.
  • Application monitoring - there are currently not many services that integrate with AWS Lambda - here your choice is simply Amazon CloudWatch, so there is no go for popular 3rd party services like NewRelic or Skylight. Rollbar has introduced AWS Lambda support just today (September 15, 2017).
  • Local development environment hassles - not all services can be run locally, thus local development with local-only resources will more problematic. To overcome this hurdle, you can use a solution like Severless Offline Plugin, which emulates Lambda locally.

Severless Node.js web service

In our serverless aws tutorial we will show you how to build an API endpoint which will take an email address and send a welcome message to it using AWS Lambda (with the Node.js runtime) and SES (Simple Email Service), Amazon’s “email sending and receiving platform for businesses and developers”.

For the purposes of this serverless web service tutorial (and easier testing) we expose our lambda function (the function that we’re going to write and then execute on AWS Lambda) via an HTTP endpoint. You could also use an internal hook from an AWS service (i.e. from Dynamo DB, which would trigger the function when a record is created, modified or removed). In a production environment you will most probably put an API Gateway in front of the Lambda proxy (which would handle all client requests as well as call other services and lambda functions based on the request) - more info can be found in the documentation.

SES Note: You need to have email addresses (for Source and Destination) or your domain verified in Amazon SES before you can send emails. You can find how to do it in the documentation.

Installation

Before we start, we need to ensure we have few things installed:

  1. Node.js - the easiest way to install is with your favorite package manager:
    • Homebrew (on OS X): brew install nodejs
    • APT (on Ubuntu / Debian): apt-get install nodejs
  2. Serverless CLI - install with npm using: npm -g install serverless command

    Your first app - serverless with aws lambda

Let’s start by bootstrapping a new project with the following command:

`serverless create --template aws-nodejs --path lambda-email-delivery`

It will create a lambda-email-delivery folder with the following files:

.
├── handler.js
└── serverless.yml

Let’s take a look at each of these a little more closely:

  • handler.js - this is where we will write our lambda function
  • serverlesss.yml - configuration for the Serverless Framework to create our service (by default it contains a lot of comments and examples)

Let’s update the serverless.yml file with the simplest configuration:

service: lambda-email-delivery

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: us-east-1

functions:
  deliver:
    handler: handler.deliver
    memorySize: 128
    description: Deliver welcome email
    events:
      - http:
          path: deliver
          method: post

Most of the attributes are self explanatory, but some of them may not be obvious:

  • stage - think about this as a pack of env variables that are assigned to a particular environment (staging, qa, production)
  • events - by default you are not able to trigger your lambda functions unless you define an event for it. In our case, we defined an http event which can be invoked using the POST method sent to the /deliver path. An event can come from an external API (http events, as well as events from other AWS services).

Let’s update our handler.js file to match the above configuration:

'use strict';

module.exports.deliver = (event, context, callback) => {
  const response = {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!'
    }),
  };

  callback(null, response);
};

This will basically return a Hello world type message in JSON format.

Serverless deployment

Now we are ready to make our first deployment. To do it run the serverless deploy command. After it finishes creating a new stack and deploying our app, we should see output with an endpoint URL:

Service Information
service: lambda-email-delivery
stage: dev
region: us-east-1
stack: lambda-email-delivery-dev
api keys:
  None
endpoints:
  POST - https://0di29xipx3.execute-api.us-east-1.amazonaws.com/dev/deliver
functions:
  deliver: lambda-email-delivery-dev-deliver

If we run CURL against the above endpoint we should see the message that we defined in the handler.js file:

$ curl -X POST https://0di29xipx3.execute-api.us-east-1.amazonaws.com/dev/deliver
`{"message":"Go Serverless v1.0! Your function executed successfully!" }`

Sending emails

So far so good. Let’s add an SES service so we can send emails from our endpoint. First let’s modify our serverless.yml file to include SES permissions for our Lambda function:

service: lambda-email-delivery

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Resource: "*"
      Action:
        - "ses:*"

functions:
  deliver:
    handler: handler.deliver
    memorySize: 128
    description: Deliver welcome email
    events:
      - http:
          path: deliver
          method: post

Now we can update our handler with code to send emails:

'use strict';

let AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';

module.exports.deliver = (event, context, callback) => {
  const requestBody = JSON.parse(event.body);
  const email = requestBody.email;
  const ses = new AWS.SES();

  ses.sendEmail({
    Source: 'noreply@example.com',
    Destination: {
      ToAddresses: [email]
    },
    Message: {
      Body: {
        Text: {
          Charset: 'UTF-8',
          Data: 'This email has been sent using AWS SES invoked by AWS Lambda.'
        }
      },
      Subject: {
        Charset: 'UTF-8',
        Data: 'Welcome from AWS Lambda'
      }
    }
  }, function(err, data) {
    if(err) {
      return console.log(err.stack);
    }

    const response = {
      statusCode: 200,
      body: JSON.stringify({ message: `Email has been sent (id: ${data.MessageId})` }),
    };
    callback(null, response);
  });
};

Testing your first serverless app

If we then re-deploy the app (we just need to run that serverless deploy command again), we should be able to send emails. Let’s test it with CURL again:

curl -H "Content-Type: application/json" -X POST -d '{"email": "user@example.com"}' https://0di29xipx3.execute-api.us-east-1.amazonaws.com/dev/deliver`

It should return a response like this:

{"message":"Email has been sent (id: 0100015e0f434792-2c534aa5-53d0-44c1-ad5f-d7637fac5ac5-000000)"}.

Summary

This is just the tip of the iceberg when it comes to what can be done with Serverless and AWS Lambda - the sky really is the limit. Why not play around a little yourself and see what you can come up with? Make sure to stay tuned to our blog for more examples.

Want to know how using Serverless and AWS Lambda can save your business money? With a different way to run your apps, priced according to execution it is possible. For more on serverless development services, or to request an evaluation of your current systems to see if this will work for you, get in contact with our AWS team. We’re experts in helping our clients improve their ROI by tweaking systems infrastructure.