Finally, an edge runtime that works out-of-the-box with Next.js, Remix, Nuxt, and more. Check it out!

Lambda, DynamoDB, and API Gateway for your Jamstack App

Creating an API with AWS: Lambda, DynamoDB, and API Gateway

This article is intended for those who are new to creating APIs with AWS. It assumes no prior knowledge, and we’ll link off to any additional features that are out of scope. By the end, you’ll set up an entire API using DynamoDB and Lambda for your application! APIs have become an important piece of modern application development, we can use them to create full stack apps, performing all CRUD operations using the technologies in this tutorial.

Today, we’ll incorporate this API into a Jamstack app and deploy it using Netlify, including using environment variables to store the key. Let’s get started!

If this is your first time creating an AWS account, chances are you will log in and feel a little overwhelmed. AWS is great because it has a ton of options. AWS is disorienting because it has a lot of options. If you ever get lost, have no fear. You can log into the console, https://us-east-2.console.aws.amazon.com/, and search for the service you’re looking for. Once you’ve looked for it a few times, they will “pin” your usual suspects to the search, which is handy.

Why are we using these tools?

  • DynamoDB is a fully managed, highly available distributed database. It takes care of replicating your data across many regions without a lot of administration. It offers fast performance and scalability without hiccups in your service, which makes it an excellent tool for our use in an application.

  • Lambda is so well-known for Serverless Functions that it’s a bit like Kleenex, sometimes people say Lambda when they mean Functions. :) Lambda lets us execute event-based logic without having to manage or provision servers. We’ll be using Lambda to express in a function what shape of data we’d like to retrieve from DynamoDB.

  • API Gateway is pretty well named :) It integrates with Lambda or other backend services to provide a proxy to accept API calls, aggregate the services to fulfill them, and return the appropriate result. It provides tools for the requests, such as testing and modeling.

Let’s Store Some Data with DynamoDB

Go to the AWS management console and search for DynamoDB, or follow this link. You’ll be brought to an overview screen with a big blue button that says “Create Table”, go ahead and click that.

We’re going to name our DynamoDB table, “restaurants”, and use an “id” as a string as the primary key. You don’t have to name it “id”, but I do suggest using a string for the ID. Click “create” when done.

After it’s finished being set up, we’ll click on the “Items” tab. We’ll start filling out the items I’m going to store and their types by clicking “Create Item”.

We’ll add in some fields, you can see I’ve made it a little complex to show all of the different types we can have, and because that’s more true to real life. I’ve used this quick UUID generator for the IDs, which I have given to each item as well as each nested item I might retrieve. You can use the command line for this task, there are a few tools that help you do so like this one for VS Code. For the purposes of this tutorial, we’ll mainly show things in the console.

DynamoDB Creating an item animation

Now you can see the table populated with items:

DynamoDB table with populated items

Of course, if you work with DynamoDB a lot, you probably don’t want to enter this all manually in the GUI. AWS has a command line tool, the instructions for installation are here.

Once you have it installed you can run:

aws dynamodb help

And it will output a ton of useful methods available to you.

In order to create a new table, we can run:

aws dynamodb create-table \
--table-name Restaurants \
--attribute-definitions \
AttributeName=Name,AttributeType=S \
--key-schema \
AttributeName=Name,KeyType=HASH \
--provisioned-throughput \
ReadCapacityUnits=10,WriteCapacityUnits=5

Which will return something like this:

{
"TableDescription": {
"AttributeDefinitions": [
{
"AttributeName": "Name",
"AttributeType": "S"
}
],
"TableName": "Restaurants",
"KeySchema": [
{
"AttributeName": "Name",
"KeyType": "HASH"
}
],
"TableStatus": "CREATING",
"CreationDateTime": "2020-08-20T22:27:32.530000-06:00",
"ProvisionedThroughput": {
"NumberOfDecreasesToday": 0,
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 5
},
"TableSizeBytes": 0,
"ItemCount": 0,
"TableArn": "arn:aws:dynamodb:us-east-2:442583039243:table/Trial",
"TableId": "d6d6337e-0052-4f69-a30b-160155071e97"
}
}

If you log back into the console, you’ll see your new table in the UI! This created the table, we have not yet put anything into it :).

aws dynamodb put-item \
--table-name Trial \
--item \
'{"Name": {"S": "All That and Dim Sum"}}'

Now we have our first row of data! There’s more you can do here, but the scope gets expansive, and we still have a lot to cover. For more information on working with DynamoDB through the CLI, the docs have everything you need to know.


From here, we have a few things we’re going to need to do to make sure our API GET works properly with what we’ve just created. We’ll have to:

  • Create a Lambda function that gathers all the data from DynamoDB and returns it
  • Make sure the Lambda has the proper permissions- reading from DynamoDB, and nothing more
  • In API Gateway, we’ll proxy the Lambda to a GET method and configure it to make sure we don’t run into any CORS errors
  • Create an API key and usage parameters so that we control how our API is consumed

Let’s start with the permissions with IAM.

Creating roles in IAM

First, we’ll search for IAM, short for Identity and Access Management, and we’ll be taken to a page like this:

Identity and Access Management (IAM) welcome screen

Underneath IAM Resources, click the “Roles” link. On the following screen, click the blue button that says “Create role”, and then choose Lambda.

Identity and Access Management (IAM) create role screen

From there, we’re going to attach the permission policy we need. You might be tempted to select “AmazonDynamoDBFullAccess” but that gives extremely broad permissions, which will give permissions to absolutely all permissions within Dynamo, and will present a security risk.

Instead, we’ll create our own policy that is specific both to this exact DynamoDB table and also to what we intend to do with it. Go to the main IAM page and select “policies” from the sidebar, and then click the big blue “create policy” button.

From here I will select “DynamoDB” as the service. Then under Actions, I’ll define what I need to do- for this purpose I’ll select “Read” and open the dropdown- from here what I need is “scan”, as that’s the method I’ll use for retrieving information from our table with Lambda.

Identity and Access Management (IAM) access level role screen

Next you’ll see a dropdown called “Resources”- for this entry you’ll need to open a new tab and go back to DynamoDB, click on the table, and lower down in the list in Table Details, you’ll see “Amazon Resource Name (ARN)” - copy that value and past that into resources. This will allow AWS to know particularly which table you are associating with the policy.

When you create the policy, I suggest you name them something related to their purpose, because you will collect a few of them over time. This specificity will be useful later, as you can easily traverse and navigate them.