Deploy Node.js Serverless Framework app with DynamoDB, S3 and Cognito in 10 Steps

First off, check out the steps outlined in

Step 1: Create an AWS account

You must enter a credit or debit card to get to this page.

Step 2: Create IAM user

Search “IAM”

Head to the Users tab on the left and select “Add User”.

Page for adding a user. Click Next.

Give yourself Administrator Access by searching “administratoraccess” and checking the box.

Then click Next and Create User.

On the next screen get your Access key ID and Secret access key. Do not post them on the internet or to github! People can use these credentials to rack up charges to your credit card so beware.

Beware of AWS charges to your account

Step 3: Configure the Serverless AWS Command Line Interface (CLI)

Install the AWS command line using homebrew.

$ brew install awscli

You can also install it using pip and python. I had difficulty adding AWS to my path. Homebrew adds it automatically. So far so good.

The official AWS CLI install docs are avail here.

Playing matrix on my macbook #saturdays

Then run

$ aws configure

Paste in your Access key ID and Secret access key. For the region I used us-west-2 and output format pressed Enter to leave it as default. More config info here.

Step 4: Create a DynamoDB Database

Extra! Extra! Read all about it:

DynamoDB is a NoSQL database where the data is stored in tables. I’ve heard it compared to the AWS version of MongoDB, but I’m sure that is not strictly true.

Head back to the AWS admin panel and go to the DynamoDB section.

Create a table.

Press the blue button!
We’re goin blue pill up in hurrr

Leave the Default Settings checked.

We are going to have users and candidates.

To learn more about how DynamoDB works, check out the DynamoDB Core Components site.

A table is a collection of items, and each item is a collection of attributes. DynamoDB uses primary keys to uniquely identify each item in a table and secondary indexes to provide more querying flexibility.

Cool. Cool. We have a database!

Step 5: Set up S3 Bucket for file uploads

AWS Simple Storage Service hosts a large portion of the internets.

Head back to console. Now we are going to the S3 section

Click Create Bucket.

Again, click the blue button.

Next up, give your bucket a name. Names must be globally unique so you cannot pick the same name as I used (below).

Pick a globally unique name for your S3 bucket.

We have to enable CORS for the bucket. We’re going to be sending requests to the bucket and CORS is a pesky issue that browsers implement to improve security. We’re going to turn it off.

Click on your S3 bucket and go to Properties. Then add CORS configuration.

Click on Add CORS Configuration

Paste in the below configuration to make CRUD requests to our bucket from the internet possible.


Step 6: Set up User Authentication with Cognito

Note: Auth0 is an alternative for user authentication with AWS + Serverless

You guessed it! Back to the home back and type in “Cognito”.

Back to the search bar!
cognito: the opposite of incognito 
for an identity to be known, no longer concealed.
No longer concealed!

Select “Manage your User Pools”.

Name your user pool and select “Review Defaults”.

I left all of the defaults and hit “Create pool” on the next page.

Once the pool is created take note of the Pool Id and Pool ARN.

Next we add an App. Select Apps from the left panel and click Add an app.

Add a new app to have access to the user pool.
Enable sign-in API for server-based authentication allows us to generate users from the CLI

Record your App name and App client id. I’m storing all of these credentials on Notepad, pasting them in to reference later!

You can store all of your credentials in Notepad or word document to reference later!

So far we have generated Access key ID, Secret access key, Pool Id, Pool ARN, App name and App client id.

The users pool is set up to store users and authenticate access to our API. If you are following along using the serverless-stack tutorial we are currently here.

Step 7: Create a test user

First run the command to generate a user.

$ aws cognito-idp sign-up \
--username admin \
--password Passw0rd! \
--user-attributes Name=email,
This will be the output for generating a user

As we can see above the user has not verified their account so UserConfirmed is false. To confirm the user run:

$ aws cognito-idp admin-confirm-sign-up \
--user-pool-id YOUR_USER_POOL_ID \
--username admin

Step 8: Manage Federated Identities

This is essentially part 2 for configuring Amazon Cognito. This section is more fully outlined here.

This creates a new identity pool

Next go into the “Role Summary” section and Edit the Policy Document. A warning will pop up letting you know to read the documentation.

We get a warning before editing the Policy Document.

Paste in this JSON for the policy:

"Version": "2012-10-17",
"Statement": [
"Effect": "Allow",
"Action": [
"Resource": [
"Effect": "Allow",
"Action": [
"Resource": [

For the YOUR_S3_UPLOADS_BUCKET_NAME section use the name of your s3 bucket. So for me it was connor11528-candidates (as pictured in S3 section above).

Next, we go to Dashboard and select Edit Identity Pool.

Go to Dashboard on left and click Edit identity pool on top right.

Save the Identity pool ID to your notepad.

Step 9: Set up the Serverless Framework

Finally we get to use some Node.js!

Now we have set up our AWS environment, time to bust out the Javascripts!

Create a folder for your project code and install the serverless package through npm (or yarn). Then generate our application files with the serverless create command, as outlined below.

$ mkdir candidates-app
$ cd candidates-app
$ npm i serverless -g
$ serverless create --template aws-nodejs

Cool! We created an app with a handler.js and serverless.yml files.

Next create a package.json and install some dependencies with the commands below.

$ npm init -y
$ npm install uuid --save

This uuid package will help us later on when querying DynamoDB.

Update the serverless.yml file like so:

service: candidates-app
name: aws
runtime: nodejs4.3
stage: prod
handler: handler.hello
- http:
path: hello
method: get
cors: true

Change up the handler.js function to simplify the JSON we return to the browser:

'use strict';
module.exports.hello = (event, context, callback) => {
const response = {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!'
callback(null, response);
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });

Step 10: Deploy the application

$ serverless deploy
Output for a successful deploy!

Now we can paste the endpoints code into our browser to view our JSON output!

Endpoint LIVE DEMO.

The source code is available here: (Give it 🌟 on the githubs!)

Special thanks to the Serverless team for building an awesome platform. If you enjoyed this article please give it a ❤ recommend or share on twitter.

Thanks for reading!

Show your support

Clapping shows how much you appreciated Connor Leech’s story.