Yesterday, I was able to leave work early and make it to the AWS popup loft in Soho NYC before they closed. It's pretty awesome because it's 100% free. They have a ton of desks, chairs, free wifi, even snacks and coffee. It's just an open place in NYC where you can go, hang out, and work on stuff. I would go there a lot back when I was in between jobs, but this time I had different purpose- to talk to an AWS architect about NodeJS and Lambda.
I actually forget the guy's name that I talked to, but he was super knowledgable and walked me through all of the things that I needed to do to get started with Node on Lambda. Basically, I had a few node scripts on a regular linux box, but I had clients that kept asking me about Lambda. They had been hearing about how it was so much cheaper and that serverless backend was the hot new thing. So I looked into it. I watched a few videos and read a few blogs, but some things were still unclear. I felt really good about it after leaving the session with the architect, and I'm going to try to write down here the things I learned from him.
Even when using a regular linux instance without Lambda, there are basically two things that will trigger your script to run. They are 1) you get a request from somewhere and want to handle it, or 2) you have a cron job that triggers the script. If you have a front-end for a web app and you want to send some information to your server for it to be processed and stored somewhere, that's a normal REST call and would use the first method. If you have, say, a script that pulls stock information every weekday at 9:15am and stores it without you needing to call to it then you'd go with method two. In Lambda the part that accepts REST calls and triggers your Lambda function is called API Gateway, and the thing that triggers Lambda functions as cron-style scheduled tasks is called CloudWatch Events. These are slightly different, and you'll probably want to go with different blueprints here so I'll go over that next.
After clicking on the button for Lambda in the AWS console, the first page it brings you to is the Select blueprint screen. The key thing to remember here is that the blueprint really doesn't matter. If you choose a blueprint it will just fill out the form on the next page with some code already. Ultimately, the Lambda function will do what you tell it to, but it can be nice to start out with a stub especially if it's already doing exactly what you wanted to do. I usually like to sort by the newest Node.js version by choosing from the dropdown on this page.
For example, if you want to make a function that triggers when a front-end app makes an http call to your server, you might start with the microservice-http-endpoint blueprint. A lot of times when I'm making scheduled node tasks I'll just start with the hello-world nodejs blueprint. Let's click on this one and take a look at the next page.
On the next page you'll immediately see three textboxes. The runtime was already chosen on the last page when we sorted the blueprints with the dropdown. The name and description are basically just for you so that you can remember what this function is doing.
Here, you have three options for telling lambda exactly what code you want run when this function is triggered. The simplest method is to just type directly in the little text area they give you. This method has some serious limitations including the fact that you can't include your node modules and external libraries. If you want to do that then you must zip up your project and upload it or use S3.
If you are using a zip file, make sure that the "root file" matches what you enter into the Handler field (coming up soon). Zip up your node modules, dependencies and all, into one .zip file. Then just click the upload button- pretty straightforward.
Notice the 10mb warning in the screenshot above. If your zip file is larger than 10mb than this upload area won't take it. In that case you'll want to point your Lambda function to a file in S3. In S3 you can set up a folder for this particular Lambda function project. Inside of it you can put your root js file, any other supporting files, and your node_modules dependencies folder. In the S3 link URL input box you would just enter the url link to the root js file.
The Handler field is super important to getting your Lambda function working properly. The default value in the hello-world blueprint is index.handler. The first part of this (index) represents the name of the root file, and the second part is the name of the function in the code that you want Lambda to call when it is triggered by API gateway or a scheduled event.
This means that if you created your own zip file or are pointing to an S3 file, and you named this root file "root.js" then in the Handler field here you would enter root.hander. But this "handler" part can be anything you want also. When we go back to the Edit code inline option we can see that (assuming you also chose the hello-world blueprint) in the code text area they have written this:
They are using some fancy arrow syntax here, but basically they are saying, "exports.handler = some function". The exports allows external files to see this function, and it's how Lambda hooks in. In other words, this function is the entry point for how Lambda kicks off your node script. So if you wanted Lambda to run the whatever function in your root.js file then you would enter root.whatever into the Handler field.
The role system is a pretty neat feature and allows you to give your Lambda function access to other AWS services like DynamoDB or S3. I usually just choose Basic Execution Role here. This should bring you to another page, and if you expand the Policy Document with the arrow button then you can see it's just a short JSON file that allows some logging (which you can see in CloudWatch).
The advanced settings let you specify if you need more memory of time for your function to execute. Fo this I recommend just leaving it as small as possible and increasing it later if you functions start error'ing out. The VPC allows you to have a very secure connection to other AWS services, but it comes at the cost of locking your function out from external api calls. I almost always am calling out to some external API from the Lambda function so I normally leave this as No VPC.
On the next page you can review your settings. If everything looks good, hit the
You should land on a page that gives you a nice happy success message and allows you to edit properties about your Lambda function if you want to.
Great! We've now set up a Node.js script in AWS Lambda, but this is just the beginning. I'm going to write separate posts for these, but the next thing to do would be either connect this Lambda function to a REST call with API Gateway or to have it be run as just a scheduled event.
The AWS architect pointed out to me that if you're doing it right, Lambda isn't all that much better than a regular linux box setup. With elastic beanstalk you can easily have AWS automatically add and remove severs to a cluster all behind the scenes which let you easily scale your backend in a cost-effective manner. He also reassured me that Node.js's underlying architecture makes it super simple and reliable to do this. Some people just like controlling their own box, don't like the long forms in AWS Lambda, or just don't trust AWS. For whatever reason, it's the end of the world if can't or don't want to use Lambda. However, Lambda is very cost effective, is pretty easy to use, and it's damn cool telling people you have a fully serverless NodeJS backend.
The posts on this site are written and maintained by Jim Lynch. About Jim...