I was looking for some hands-on experience on serverless framework and NodeJS to apply my knowledge from various tutorials. So, I decided to build a serverless application using AWS Lambda, and am excited to share my journey with you. I created a Lambda function using NodeJS which can perform CRUD operations on AWS DynamoDB.
Let's start with understanding serverless application components:
- Functions: They execute code and respond to specific events that trigger them. They can be developed through IBM Open Whisk, Google cloud functions, Azure functions, and AWS Lambda.
- Events: They can be anything ranging from http request events, scheduler events like cron, or specific infrastructure provider events like AWS s3 file upload. Events can be generated from:
- API Gateway,
- Changes that happen in S3 bucket,
- CloudWatch logs in AWS,
- Updates to DynamoDB tables, and
- IOT devices and even from Alexa.
- Resources: A resource can be DynamoDB as a serverless database or an AWS Simple Storage Service bucket. However, we can also have any other AWS resource that can be described in a Cloud Formation template. This can be anything ranging from Cloud Front distribution networks to speed up the delivery of files to your users or the Amazon Cognito user pool to manage the users of a mobile application.
- Services: A service is like a project. It’s where you define your AWS Lambda functions, the events that trigger them and any AWS infrastructure resource they require, all in a file called serverless.yml. It encapsulates functions, resources and events so that you can logically separate them from other services.
What’s in a service:
Serverless.yml: The main configuration file which defines all configurations for a service. It defines a name for the service, determines which service provider and runtime the service will be using and specifies files and directories that explicitly should or shouldn’t be included in packaging the function code. It also defines any resources required by the service like DynamoDB table. And, it defines all the functions within the service, the events that will trigger them and any sort of configuration required for the functions themselves.
- Functions: Function code is triggered in response to events. Each serverless function in AWS has an event, a context and a callback. The event object contains the data passed into the function from whatever event triggers it. Most often, functions will process an event object and determine how to act on that information. The context object contains a variety of information about the function such as the function’s name, memory limit of the function and the log group name for the function. It also provides the method to get the remaining time left for the function before timeout would occur. Callback is used to pass back information to the function caller.
- Dependency: Dependencies are used to enhance service functionality. These can be anything from the snippets of custom code included in the same folder to full blown npm packages. It can also be serverless framework plugins that enhance and extend the functionality of framework itself.
Let me show you how I created my own delivery service.
Order delivery service overview:
I created a serverless API to handle incoming HTTP requests. That API allowed me to create, read, update and delete the items inside of a DynamoDB table that I used to store information about order deliveries.
- I needed an AWS account with admin rights and programmatic access.
- I made sure AWS CLI, Serverless, Node and npm were installed.
First, I started up a service and installed dependencies:
- I created a serverless framework service from a template. Command: serverless create --template aws-nodejs --path servicename
- I installed any dependencies. Command: npm init and npm install your-dependenciesNext, I worked on configuration settings by opening the serverless.yml file and specifying the details of the service. It included service name, provider and functions.
From there, I turned to the writing functions. I used code used within my service along with the events that trigger them.
Now, I moved into serverless deployment. My options were:
Sls deploy function –function list
Sls deploy --package package-path
When I ran a command like serverless deploy, the framework reviewed my serverless.yml file then created a CloudFormation template from that file. It also zipped up the dependencies and sent them over to AWS S3 for later use. The CloudFormation template was then passed to AWS to create any resources for the service that I needed. This included API, databases or other resources required for the service. CloudFormation then created the functions themselves from the zip deployment packages that are stored in S3. And when everything finished, the serverless framework displayed the successful status of the deployment.
Lastly, I began the testing phase.
- I wrote testable function code—not testable Lambda functions. I did this because my function code might be usable on other infrastructure providers.
- Then, I tried to separate business logic from infrastructure-specific code. This helped to run unit test for business logic and integration tests with other services.
Here are some screenshots of the output:
I created items in DynamoDB table using POST.
AWS Dynamo DB Table
Result of GET request on OrderDelivery
Hopefully, this post helped you learn something new about building a serverless application on AWS Lambda and NodeJS. I wanted to share my experiences to help you get started on build your own application. You can access my full code at my GitHub Link to learn more.