DEV Community

Cover image for Getting Started with AWS Lambda and Node.js
Adnan Rahić
Adnan Rahić

Posted on • Updated on

Getting Started with AWS Lambda and Node.js

Once upon a time, not so long ago, a word caught my ear. Lambda. That struck a chord, remembering the good old days of playing Half-Life as a kid. Little did I know what AWS Lambda was, and how incredibly awesome it is. If you're intrigued, stick around. I'll only take a few minutes out of your already busy day, and you surely won't mind.

Function as a Service

Let's jump right in. The architecture AWS Lambda belongs to is called either Serverless Computing or Function as a Service. It's groundbreaking because of the lack of servers. That sounds strange. Well the code is not running on potatoes, is it!? Okay, that's just a saying. What's actually going on is that you, the developer, don't need to worry about the infrastructure your code is running on. You deploy the code into the cloud and it handles the creation of all needed resources by itself. But how? Containers!

No, not those. These!

Docker is the world’s leading software container platform. Developers use Docker to eliminate “works on my machine” problems when collaborating on code with co-workers. Operators use Docker to run and manage apps side-by-side in isolated containers to get better compute density. Enterprises use Docker to build agile software delivery pipelines to ship new features faster, more securely and with confidence for both Linux, Windows Server, and Linux-on-mainframe apps.

Every time an AWS Lambda Function is created, a container is spun up to serve it. It's actually not a Docker container though, rather a proprietary container built by AWS. I just used the example so you would understand it a bit easier.

The code is deployed into the container and then executed. Hence making every subsequent request faster because AWS is skipping the initial creation of the container if it already exists.

Creating your First Function

Before you can even see the code you need to create a new function in the AWS console. Which means you need an AWS account. If you don't have an account, don't hesitate to create one, they have incredible free tiers that include various services and last up to 12 months.

Moving on, fire up a browser and navigate to your account. From there you need to find Lambda. Press the services dropdown and select Lambda.

AWS Services

You'll land on the Lambda homepage with a big orange button prompting you to create a new function. Well, don't keep it waiting any longer, press it.

Create a Function

This will take you to the main function creation wizard. As this example will cover a basic function that will simulate a dice throw, let's forget about the blueprints and just author one from scratch.

Awesome! Now you just need to add a name and role for the function and finally start writing some code. Regarding the role, feel free to just pick an existing role such as lambda_basic_execution. It will more than suffice for this simple example. Make sure not to forget adding Node.js 8.10 as the runtime either. Finally, go ahead and create the function.

Function Basic Info

Great! Now you're finally seeing some code. Much better. Let's dive in. There are several options to take into consideration. The code entry type option sets how you will add code to the function. It can either be inline, upload a .zip file, or upload from S3. We'll be using the first option, editing inline. For small functions, it's totally fine to write code inline. But when you have more code, it gets very tiresome. That's why there is a .zip upload option which we will touch upon later as well.

Set the runtime to Node.js 8.10, which is the latest supported version of Node.js for Lambda at the time of this writing. The handler can stay the same as well. Here, the index stands for the name of the file, while handler is the name of the function.

Function Inline Editor

With previous versions of Node.js on AWS Lambda (6.10), there were 3 main parameters:

  • The event parameter contains the current event info. That means the event that triggers the function will send along information to the function to use. An example would be the data an HTTP request sends along to the endpoint, such as whether it has request parameters or a body.
  • The context contains all the information about the function itself. How long it has been running, how much memory it's consuming among other things. This is viewed as the runtime information.
  • The callback is pretty self-explanatory. When you want to tell the function to end its execution, you invoke the callback. It takes two parameters, the first is an error, the second is the data you wish to send back as the response of the Lambda function.

Things have changed with Node.js 8.10 because of the addition of async/await support. The handler can now accept a promise value. This is why we can now assign an async function to the handler, and return a promise directly. No more stupid callback parameters. So awesome!

Writing Some Logic

That's enough with the set up for now. Let's code something.

We're starting out with this snippet of code. The goal is to write a piece of code that will mimic the roll of a dice.

exports.handler = async (event) => {
  // TODO implement
  return 'Hello from Lambda';
};
Enter fullscreen mode Exit fullscreen mode

Here goes nothing.

exports.handler = async (event) => {
  const min = 1;
  const max = 6;    
  const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
  const message = 'Your dice throw resulted in: ' + randomNumber;
  return message;
};
Enter fullscreen mode Exit fullscreen mode

Nice! That does the trick. Now the function will return a random number between 1 and 6. With that out of the way let's test it. Press the orange test button and proceed to create a simple test event. Give it a funky name for no particular reason. Just for the fun of having a test event named FunkyName. Now you can go ahead and test the function. After pressing the test button you'll see something like this.

Function Testing

The section bordered with the dashed outline shows the function output, more precisely the return value that got sent back by the function.

That was fun! You now have a roll a dice function, but no way of triggering it outside of AWS, yet.

Connecting an API

Here comes the crucial part. How do you think a lambda function knows how to start its execution? Voodoo? Magic? No, sadly not. Every function invocation is triggered by an event. It can be an when an image gets uploaded to S3, it can be an Amazon Alexa skill, or just a regular HTTP request.

Let's create an HTTP event and tell it to invoke our function. To be able to do this you first need to jump over to API Gateway in the AWS console. In the services dropdown pick API Gateway, and you'll land here.

Get Started API Gateway

You'll immediately be prompted to create an API. Ignore all the suggestions and just pick New API and input a name for your API. I'm going to stick with FunkyApi, it just sounds right. Go ahead and hit create.

Create API

Now comes the fun part. Finally get to hook up the API to the function. First press the Actions dropdown and pick Create method. You'll see another smaller dropdown show up. Press it, and pick GET. Set the integration type to Lambda Function, select the region where you created the function and write the name of your function.

Create Method and Hook Lambda

Hit save and rejoice!

The API is set up and ready. You now only need to deploy it. Press the Actions dropdown once again and hit Deploy API. Pick a new Deployment Stage, write down dev as the stage name and you're ready to deploy the API.

Deploy API

Finally! The API endpoint is ready. You now have access to the Invoke URL on the dev Stage Editor.

API has been Deployed

Feel free to open up the API endpoint in a browser window and check the output. What do you see? No really, what do you see? A random number between 1 and 6 should be returned back. How awesome is this!? In less than 5 minutes you've created a Lambda function, connected it to API Gateway and created an endpoint to be consumed whenever you like.

Uploading Code with a ZIP

What if you need to use some modules from npm? You can't add them inline. There has to be a way of running code with dependencies. Well, there is, but it's a bit tricky to get right. Nevertheless, let's get on with it!

First of all, create a directory and initialize npm.

$ mkdir roll-a-dice \
    && cd roll-a-dice \
    && npm init -y
Enter fullscreen mode Exit fullscreen mode

Once you've done this, go ahead and install moment, a simple datetime library.

$ npm install moment --save
Enter fullscreen mode Exit fullscreen mode

This will create a node_modules folder with the required dependencies. To include them you need to compress all the files and upload the .ZIP file to Lambda.

Important Note: Only compress the files and folders inside of the project directory. Do NOT zip the whole folder. If you do it will break the configuration and the Lambda function will fail!

Before you go ahead and compress the files add some code with the new npm module you just installed to make sure the Lambda function uses it.

Create a new file in the project directory and name it index.js. Paste the existing lambda function from AWS into the file and edit it slightly.

const moment = require('moment');
exports.handler = async (event) => {
  const min = 1;
  const max = 6;

  const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min;
  const now = moment().format();

  const message = 'Your dice throw resulted in ' + 
  randomNumber + ' and was issued at ' + now;

  return message;
};
Enter fullscreen mode Exit fullscreen mode

Save all the files and go ahead and zip them up. Remember, only the files and folders within the roll-a-dice directory.

You now have a .ZIP file. Go ahead and jump back to the AWS Console.

Upload ZIP

Change the Code entry type to Upload a .ZIP file and upload the file you just recently compressed. Great! Now, scroll back to the top of the page and press the big orange button once again to Save and Test the function.

Test Function

Nice! It works and it's showing the current date and time. You zipped the function and npm module correctly. Just in case, jump back to a browser window and try the endpoint once again. It should now show the updated message.

What now? Start coding!

Lambda is an incredible tool which works well with an abundance of other services on AWS. Lambda functions can be invoked in response to events like file uploads, they can also be used for chatbots, REST APIs and much, much more.

This simple API example we coded above is just the beginning. But you can see the point. So much overhead is avoided with just worrying about the code, not caring about the underlying infrastructure. I urge you to continue playing with this technology as it will only get more popular in the time to come. Just start coding. Whatever it may be, it doesn't matter. Just start writing code, because you will learn the most by doing it yourself.

We at Tracetest want to create an easier way of testing and troubleshooting serverless apps. If you have any questions feel free to let me know in the comments below.

If you missed any of the steps above, here's the repository with all the code.

Hope you guys and girls enjoyed reading this as much as I enjoyed writing it. Until next time, be curious and have fun.


Disclaimer: Tracetest is sponsoring this blogpost. Use observability to reduce time and effort in test creation + troubleshooting by 80%.


Top comments (19)

Collapse
 
maxart2501 profile image
Massimo Artizzu

Nice one, Adnan. I'm bookmarking this article.
It would be interesting to know about a couple more things:

  • Reading/writing to disk: is it allowed/slow/limited/expensive?
  • Using a DB like MySQL or Redis or whatever: how to?
  • How reliable are the free tiers? Do they take long to start up?
  • Nice if you happen to know: how does AWS Lambda compare to other lambda services, e.g. Google Functions?
Collapse
 
adnanrahic profile image
Adnan Rahić

Thanks! Glad you're interested in learning more.

  • Read/Write to Disk: There are a few things to wrap your head around regarding serverless architectures in general. There's no persistent storage because it is essentially a container. You have a tiny /tmp dir where you can write to disk, but you seriously do not want to.
  • DB: You have to use a database which is hosted separately. You can, of course, spin up a server and host it yourself, but that's too painful for me so I just use DBaaS solutions such as MongoDB Atlas or AWS RDS. But you can use whatever you like here pretty much. I explained hooking up Atlas to Lambda here.
  • Free tiers: AWS Lambda's free tier is only about invocations and compute time. The performance and start-up speeds are the same nevertheless. Lambda cold starts are usually between 1 and 3 seconds. Which is manageable if you use warm-up scripts and proper tooling. I'd suggest you do use the Serverless Framework and some monitoring solution like Dashbird if you want to create production apps. Take a look at the articles covering all things tagged #serverless on my profile
  • Other FaaS solutions: AWS Lambda is by far the most used and covers most languages. But Google Cloud Functions (Firebase Functions) are great as well. Of course Azure has their Functions too. All of those get the job done the same way. Even the pricing is literally the same. It all boils down to which provider you use and you pick your FaaS solution based on that.

Hope this clears things up. :)

Collapse
 
maxart2501 profile image
Massimo Artizzu

Awesome, thank you! :D

Collapse
 
shmdhussain12 profile image
Mohamed Hussain • Edited

Great Adnan...Clear Explanation on what to do with AWS Lamdba...one question , is that possible to stop the api gateway which we created for roll-a-dice temporarily, if so how could I do it?....

Do we need to include the node_modules folder when we upload the zip to lambda?

Collapse
 
adnanrahic profile image
Adnan Rahić

You can't "stop" the API Gateway entirely, but you can add an API Key to rate-limit the endpoint.

Yes, you need to include the node_modules. I tend to write Lambda code locally and use the Serverless Framework to deploy the code and resources. Check out this article I wrote to learn how.

Collapse
 
ankursingh16 profile image
AnkurSingh16

Thats a very nice article Adnan. I'm looking to find a way to write Lambda code in local IDE so that I can have version control. Any suggestions?

Collapse
 
adnanrahic profile image
Adnan Rahić

I use VSCode and the Serverless Framework to manage my resources and code. Check out this article I wrote to learn how.

Collapse
 
mistermoses profile image
Dan

The upload zip instructions don't make sense. If I run mkdir roll-a-dice && npm init -y then the node_modules directory will be outside my project directory and will not be include in the zip.

Collapse
 
adnanrahic profile image
Adnan Rahić

Oh, that's a typo. Thanks for noticing Dan! I've fixed it now.

Collapse
 
chathula profile image
Chathula Sampath

great explanation!!! :D

Collapse
 
adnanrahic profile image
Adnan Rahić

Glad you liked it!

Collapse
 
rishinharis profile image
Rishin Haris

Hi Adnan,
Can you tell me how to host nuxt js server in lambda?

Collapse
 
adnanrahic profile image
Adnan Rahić

That's actually a great question. I haven't tried it yet, but I'd say it's better to use nuxt generate and host static content on S3. If you get around to trying it, feel free to get in touch with me!

Collapse
 
avalander profile image
Avalander

Awesome article, thanks for writing! I've been trying to learn AWS lambda recently, but I find the official docs rather confusing, this article helped a lot!

Collapse
 
adnanrahic profile image
Adnan Rahić

Glad it helped! I can understand the pain of reading the AWS docs. They are surprisingly bad for such a huge provider.

Collapse
 
buntine profile image
Andrew Buntine

Nice article. It would also be interesting to talk about receiving input to the lambda handler. I see the event argument is passed into the function but it's never used.

Collapse
 
adnanrahic profile image
Adnan Rahić

Thanks! :)
Here's another article I wrote a while back.

It's a bit more detailed, with examples of receiving input. :)

Collapse
 
crisp3333 profile image
Gabi • Edited

I assumed you wanted us to cd into 'roll-a-dice' directory and do an 'npm install moment --save' (for the uploading zip folder part).

Collapse
 
sbasaez profile image
sbasaez

adnan excelente articulo lo lei y me quedo mucho mas claro aws lambda si tubiera mas informacion y la puedes compartir seria de gran utilidad

saludos