How To Build a Serverless API With DynamoDB, AWS Lambda, and API Gateway

AWS all the things!

Andrew Bestbier
Oct 22 · 9 min read

Last week I wrote a guide to building a simple Serverless API . This piece goes into more depth by building a fully functional Serverless CRUD API that utilises DynamoDB. In this guide, we’ll build an API that has the following operations:

  • GET /books
  • POST /books
  • GET /books/{id}
  • PUT /books/{id}
  • DELETE /books/{id}

Technologies Used

This guide uses the following technologies:


Database Setup

Log in to AWS and navigate to the DynamoDB service. Then click Create table:

Name your table (I called mine books), provide a primary key (I used id) and click Create. Your choice of a primary key is important as it uniquely identifies each item in the table, so that no two items can have the same key.

AWS will then spin up a table for you. Once this has been set up, click the Items tab. Predictably, there are no items in your table — we’ll soon add a few.


Creating the Lambda Role

If you’re unfamiliar with AWS roles, they’re essentially used to give AWS services internal access to each other. We need to create a role that we’ll assign to our Lambda functions. This role will give these functions permission to access our DynamoDB table.

Navigate over to the AWS IAM service and click Roles:

Click Create role:

Select Lambda as the service that will use the role. Then click Next: Permissions:

We now need to attach a permission policy to that role. Search for AmazonDynamoDBFullAccess, check the checkbox and click Next: Tags.

Don’t add any tags as they’re outside the scope of this piece. Click Next and, on the review page provide a name for your role (I chose crud). Finally click Create role:

Creating Book Lambda

Navigate to the Lambda service in AWS and click Create Function:

Click Author from scratch as we’re building this function from first principles. Name your function (I chose create-book), select Node as the Runtime and, for the execution role, use the role with permissions we created earlier (crud in my case). Then click Create function.

You should then see an overview page for your function which contains a code editor. We will change this code soon, but first click Test:

You will then be prompted to configure a test event that will be passed to your Lambda. For now just use the Hello World template, name your event (I named mine CreateBook) and click Save:

Click Test again and you should see a successful execution that returns Hello from Lambda :

Now we can make this function actually do something. Populate the function with the following commented code:

If you click Test you should see an execution failure. This is because the function is expecting to extract a title from the passed eventbody. We can fix this by clicking Configure test events:

Change the event to the text seen below and click Save. Don’t worry about the slightly odd format for now, this will become clearer later when we integrate this function with API Gateway. Click Test again.

{
"body": "{\"title\": \"Harry Potter\"}"
}

Hopefully, your function will execute correctly and create a Harry Potter book item in your table. To check, navigate back to your table in DynamoDb and check the Items:

Creating Get Books Lambda:

Now, rather than having to check the books through the DynamoDB UI, it would be great to rather get these through a new Lambda function. Head back to the Lambda service and click Create function again. Next, name your function (I named mine get-books) and use the crud role:

Populate your function with the following commented code:

Click Test, configure a default test event, click Create and Test the function again:

If everything is configured correctly, you should see that your function returns the books in your DynamoDB table:

Creating a GET Books API

Now that we have two functions, we can start building our first Serverless API. Head over to API Gateway and click Get Started:

Name your API (I called mine Books), select Regional and click Create API. We’re using a Regional API here as using CloudFront to spin up our API around the world is out of the scope of this guide.

Now that your API has been created, we are going to create a resource. Click the Actions drop-down and then click Create Resource.

Name your resource (I named mine books) and click Create Resource.

We now need to create various methods on your resource. Click the Actions drop-down again and this time click Create Method:

A small drop-down then appears with various HTTP methods to choose from. In our case, we are going to use the GET method. Once selected, click the circle tick icon.

On the right, you can now configure your new method. We need to link the GET books method to the get-books Lambda function we created earlier. Select Lambda Function as the integration type and specify get-books as the Lambda function, then click Save.

AWS then shows a really neat diagram of the entire flow:

Our final step is to deploy our new API resource and method. Click Actions again and Deploy API:

A modal then appears asking which stage you wish to deploy the API to. Create a new stage and name it production before clicking Deploy.

You will then be taken to the Stages screen where your deployed domain will be made available for you. Click the Invoke URL to test it out (Remember append books to the end of the provided url). You should see your books pulled through:


Creating a POST Books API

Now that the GET Books API and the get-books function have been connected, it is time to do the same for the create-book function. Head back to Resources, click the books resource, click the Actions drop down and click Create Method:

This time create a POST method and specify your Lambda function as create-book. Click Use Lambda Proxy integration and click Save.

You’ll notice that we didn’t use the Proxy integration for the GET Books method. This is because we didn’t need any of the request details sent through to the Lambda function.

However, for the POST method, we wish to pass a title of the book when hitting the API.

Deploy your API again to production and open your favourite API tool. Next, do a test POST to your API. In my case, I populated the body of the request with:

{"title":"Lord of the Rings"}

I then received a 200 in response:

If we hit the GET Books API now, we should see Lord of the Rings alongside Harry Potter:


Get Book Lambda and API

The next natural step is to create a function and API that gets an individual book. Head over to the Lambda service and create a new function entitled get-book which uses our crud IAM role.

Populate your function with the following commented code: (Take special note of the id from pathParameters extraction)

Test the function with a test event that contains an id of one of your books and that book (and only that book) should be returned:

{
"pathParameters": {
"id": "a4850b12819e5f92c216222d51757378"
}
}

Head over to API Gateway, click on books and click the Create Resource action:

This time we wish to create a resource like GET books/{id} that maps to the Lambda function we just created. So name your resource {id} and also call the Resource Path {id} :

Check Use Lambda Proxy Integration as we will want to access the id in our Lambda function, specify your function and click Save:

Next Deploy your API and test it out. Again, only the single book should be returned.


Delete/Update Book Lambda and API

To complete our API, we need to add the Delete books/{id} and Update books/{id} methods and functions. To keep this article short, I won’t provide all the screenshots for these steps as they are mostly the same as for the GET books/{id} method. It will be excellent practise for you to implement these yourself but I have provided the function code so that you don’t need to search through the DynamoDB SDK documentation:

The Delete Lambda code:

The Update Lambda code:


Conclusion

Congratulations on getting this far! If you want to extend your new API, you can (among other things):

  • Add request validation
  • Use AWS Cognito to require authentication to access your APIs
  • Deploy the API to your own custom domain
  • Use API keys to limit the API use

I encourage you to burrow deeper into the wonderful world of AWS!

Better Programming

Advice for programmers.

Andrew Bestbier

Written by

Hi! I am a JavaScript developer based in London. I love reading and writing about JavaScript, AWS and all things coding.

Better Programming

Advice for programmers.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade