10 easy Steps to create AWS Lambda functions with the Serverless Framework & Reason in AWS Cloud9
Tags: aws, cloud9, reason, serverless
Published: 2017-12-05 10:43:23

---
title: 10 easy Steps to create AWS Lambda functions with the Serverless Framework & Reason in AWS Cloud9
published: true
description: Cloud Computing TO THE MAX!
cover_image: https://thepracticaldev.s3.amazonaws.com/i/zgoqqmr7wrxubjfs10jm.jpg
tags: aws, cloud9, reason, serverless
---

_[Cover image by Kyle James on Flicker.](https://www.flickr.com/photos/jameskm03/)_

After reading [this awesome tutorial](https://dev.to/dangolant/creating-serverless-functions-with-python-and-aws-lambda-dli) by [Daniel Golant](https://twitter.com/dangolant), I tried myself at [AWS Lambda](https://aws.amazon.com/de/lambda/). To make the whole thing a bit more interesting than just using the [Serverless Framework](https://serverless.com/) with Node.js instead of Python, I added [AWS Cloud9](https://aws.amazon.com/cloud9/) and [Reason](https://reasonml.github.io/) to the mix.

## What are we working with?

There is a new online IDE called AWS Cloud9. Runs on EC2 and comes with many dev tools.

AWS Lambda is a good bit older, it's a way to run functions you code in the cloud without messing with servers. AWS just starts copies of them when you get more users.

The serverless framework is a way to make AWS Lambda more accessible, because the regular way to work with it is kind of a pain.

Reason is a language created by Facebook. With the BuckleScript compiler, which is a backend for the OCaml compiler, Reason is compiled to JavaScript. It's basically OCaml with a JavaScript like syntax.

## What needs to be done?

1. Setting up an AWS account
2. Adding an IAM user to the account
3. Adding permissions for Cloud9 and administration to that user
4. Logging into AWS with the created user
5. Creating a Cloud9 environment
6. Installing and configuring BuckleScript
7. Installing and configuring Serverless
8. Converting the JavaScript code to Reason
9. Compiling Reason to JavaScript
10. Deploying function to AWS Lambda

## How

### 1. Setting up an AWS account

First we need an AWS account to get access to the services we want to use.

You can create one [here](https://portal.aws.amazon.com/billing/signup#/start)

As you can see, 12 months of free usage are included. As long as you use the services that are elegible for the free tier you are good to go.

### 2. Adding an IAM user to the account

Next is setting up an IAM user, so you can access the services without using your _root account_.

For this, you first need to login into the [AWS Management Console](https://console.aws.amazon.com/console/home)

Top left is a _Services_ menu, where you choose _IAM_ from the _Security, Identity & Compliance_ category.

Click on _Users_ on the left and choose _Add User_.

Give it a name you can remember, preferably lower-case, also give it _programmatical access_, which is used by the serverless framework later. Also _AWS Management Console access_ so you can login with a password to create your Cloud9 environment.

Then hit _Next: Permissions_

### 3. Adding permissions for Cloud9 and administration to that user

Choose _Attach existing policies directly_.

Here you have to search for the _AdministratorAccess_ and _AWSCloud9User_ permissions and check them.

The first is needed by the serverless framework, the second, you guessed it, by Cloud9.

Now you can go to _Review_ to check if everything is alright and then _Complete_.

If you used an auto-generated password it will be shown in the _Complete_ screen, you have to __save it for login__.

_Close_ this wizard, you should now see a list of users. Click on the username of your new user.

Click on the tab _Security Credentials_, this gives you a _Console login link_, save it.

Then sign out.

### 4. Logging into AWS with the created user

Now try to login to the _AWS Management Console_ with the _Console Login Link_ you saved.

It should look like this:

    https://<NUMBER>.signin.aws.amazon.com/console

Enter the username and the password of your new user and login.

### 5. Creating a Cloud9 environment

Open the _Services_ menu on the top left and select _Cloud9_ in the _Developer Tools_ category.

Here is a button _create environment_ you have to click.

Give it a name and do the _Next step_

The configure settings can be left as they are, just the _Instance type_ needs to be change from `t2.micro` to `t2.small`, because BuckleScript will compile the OCaml compiler, which takes more than 1GB memory. We will set it back at the end of the BuckleScript installation.

The _Next step_ is a review again, click _Create environment_, this can take a few minutes.

The Cloud9 environment comes with a pre-installed EC2 instance. You get Linux, the AWS-CLI, Git, Nodejs (6.11 via nvm, can be changed) , GCC and a whole bunch of other developer tools.

### 6. Installing and configuring BuckleScript

When the whole thing has started, you can run

    npm i -g bs-platform

right out of the box. Again, because of the OCaml compilation, this takes a few minutes.

After this, you can create a Reason project with 

    bsb -init my-first-service -theme basic-reason

Now you need to change the `bsconfig.json` that was created in your new project folder, so the serverless framework later finds your output JS-files.

    suffix: ".bs.js"

to

    suffix: ".js"

You can run the compiler with `npm run build`. You should see a `lib` folder, with some temporary files and a `src/demo.js` file that is your successful build.

#### Interlude: Setting the EC2 instance back to t2.micro

After this, I suggest you go to the [AWS Management Console](https://console.aws.amazon.com/console/home), this time login with your AWS Root account user and switch back the `t2.small` instance to `t2.micro`.

Go to `Services` and `EC2` in the `Compute` category.

Select `Instances`

Click right on your Cloud9 instance with _Instance Type_ `t2.small` and set the _Instance State_ to _Stop_.

Then Click right again on this instance and use the _Instance Settings_ change _Instance Type_.

In this menu you can now choose `t2.micro`. This type will then be used if you restart the Cloud9 environment.

Sign out the root account user and sign back in as the new created user [AWS Management Console](https://console.aws.amazon.com/console/home) and go back to your Cloud9 environment _(Services -> Cloud9)_

### 7. Installing and configuring Serverless

Now we need the serverless framework to test and deploy the functions we will write to AWS Lambda.

    npm i -g serverless

Then inside you `my-first-service` project folder you need to create a serverless project with a aws-nodejs template.

    serverless create --template aws-nodejs --path my-first-service

This will create another `my-first-service` folder inside your project folder.

You need to move the two files inside this new folder.

The `handler.js` has to move from `my-first-folder/my-first-folder` to `my-first-folder/src`

The `serverless.yml` has to move from `my-first-folder/my-first-folder` to `my-first-folder`

Change the `serverless.yml` to this

```yaml
service: my-first-service

provider:
  name: aws
  runtime: nodejs6.10
  stage: dev
#  region: eu-west-1

functions:
  hello:
    handler: src/handler.hello
    events:
      - http:
          path: hello
          method: get
```

I used region `eu-west-1` this may be different for you, but this config is optional, it will use an US region on default.

As you can see, the first function `hello` is configured to run on an `HTTP GET /hello` event.

Serverless looks inside the `src/handler.js` to find an exported function `hello`.

To deploy the `hello` function created by serverless run

    serverless deploy

Cloud9 manages a pre-installed AWS-CLI for you, so the serverless framework can simply use your Cloud9 user to do its thing.

If everything went right, you will get a URL to the HTTP endpoint your AWS Lambda function is running.

To _un-deploy_ your function again you can run

    serverless remove

Also, there is a way to "test" functions locally:

    serverless invoke local --function <FUNCTION_NAME>

### 8. Converting the JavaScript code to Reason

Now that we can deploy, we need to re-write our code in Reason.

For this, rename the

    handler.js

into

    handler.re

and replace its content with

```javascript
type jsobject = {. "message": string};
[@bs.scope "JSON"] [@bs.val] external stringify : jsobject => string = "stringify";

let hello = (_event, _context, callback) => {
  let body = {
    "message" : "Hello from Reason!"
  };
  
  let response = {
    "statusCode": 200,
    "body": stringify(body)
  };

  [@bs] callback(Js.Nullable.null, response);
};
```
What does this do?

First, it makes the global `JSON.stringify` method available in Reason. Everything in Reason has to be typed, so I create a simple jsobject type for a message object and then tell Reason, that the `JSON.stringify` method expects an input of that type.

Then I define my `hello` function, that will become my AWS Lambda function. I prepend the unused arguments with an underscore, since I'm only going to use the `callback`.

In the function I create an jsobject and put it into `stringify`. This becomse the `"body"` of a (HTTP) `response` object, that also needs a `"statusCode"`.

Finally I call the `callback` function with a `null` for the error argument and my `response`. The `[@bs]` prevents the currying of the callback.

### 9. Compiling Reason to JavaScript

When we run

    npm run build

BuckleScript will create a `src/handler.js` that looks remarkably like the one we started with.

```javascript
// Generated by BUCKLESCRIPT VERSION 2.1.0, PLEASE EDIT WITH CARE
'use strict';


function hello(_, _$1, callback) {
  var body = {
    message: "Hello from Reason!"
  };
  var response = {
    statusCode: 200,
    body: JSON.stringify(body)
  };
  return callback(null, response);
}

exports.hello = hello;
/* No side effect */
```

Since a Reason file is a module and all Reason modules export their members by default, we don't need to explicitly export the function in the Reason code, but as we see, it will be exported non the less.

### 10. Deploying function to AWS Lambda

Now we can run the deployment again

    serverless deploy

and can navigate to the endpoint we get to call our function, this time written in Reason.

This should now print

    {"message": "Hello from Reason!"}

## Conclusion

This is a very simple example of how to get these two bleeding edge technologies to work together.

Reason AND Serverless both keep their fingers to themselves and let us interface them purely with JavaScript files. Truly good team players.

The Reason JS-Interopt is a bit chatty, but at least you get a completely _and_ soundly typed codebase out of this.

When you know the structure of lambda's `event` and `context` objects, you can use it to type your functions even more than I showed in this small example, which should decrease errors very much.

AWS Cloud9 is nice too, but since it is also rather new, it doesn't have all the plugins you're acustomed to by using Atom or VSCode. It's certainly cool that it comes preinstalled with many dev tools and even sets up the AWS-CLI, but at the moment I don't think it's a viable alternative to _on-premise_ editors.

_Thanks to [Daniel Golant](https://twitter.com/dangolant) to check if I wrote crap :D_