Part 2: Configure the backend
Tags: aws, cloud, tutorial
Published: 2023-10-04 11:52:59

## Included in this chapter... 
- Objective
- AWS services used
- Step 1: Create the DynamoDB table
- Step 2: Create the IAM Role
- Step 3: Create the AWS Lambda function
- Step 4: Create the API Gateway configuration
- Summary


---

## Objective
For this part of implementing the **website’s visitor counter** I will be working on several steps as follows:

  1. Create a **DynamoDB** table that will contain a single row of two columns, the latter column will contain the current visitor count value. 
  2. Create the **IAM policy** and **role** to allow **Lambda** to access and update **DynamoDB**.
  3. Create a **Lambda** function that will 1) access **DynamoDB** and get the current visitor count, increase it by 1 and 2) replace replace the value back into **DynamoDB**.
  4. Create an **API Gateway** that will invoke the above **Lambda** function, the API will later be configured to CloudFront and triggered when the resume page is opened.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5shb0qjp97ncumgdxbxx.png)


---

## AWS services used
- DynamoDB
- IAM
- AWS Lambda
- API Gateway

---


## Step 1: DynamoDB - create the table

- Open DynamoDB from the AWS console
- Select the region as ‘**Europe (Paris)**’, ‘**eu-west-3’**- Click on ‘**Create table**’



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tlfij7i4el6u6s3snp9z.png)

In the following '**Create table**' page, enter the following details:

- **Table details**
   - Add the table name
   - Partition key
      - Add ‘**id**’ and select ‘**String**’
- **Table settings**
   - Select ‘**Customize settings**’
- **Read/write capacity settings**
   - Select ‘**On-demand**’
- **Scroll to bottom** 
   - and click on ‘**Create table**’



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekpg9h37cetct3ug77cs.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19gv82fymthggrteizcm.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u35z5oyx8ztk2e98bfhs.png)

-- 

The below image shows how the table will look once set up. Note that the row count will not increase, only value under '**visitor_count**' will be updated.


![visitor count](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5r135nr51boj3ngu960l.png)

---

## Step 2: IAM - Create the Role
To enable Lambda to securely access DynamoDB I will need to **create a policy and attach it to an IAM role**, the role will later be attached to the Lambda function. The  role will be based on a policy of **allowing ‘read’, ‘write’ and ‘update’ operations** when Lambda connects to DynamoDB.




- Open the IAM console
- Click on ‘**Policies**’ and then ‘**Create Policy**’



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d7ajjoriy91n1u0gd9j1.png)

---
#### Policy creation (AWS step 1 of 2): Specify permissions

Click on the ‘**JSON**’ tab and enter the below code into the ‘**Policy editor**’ 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/abj7q4lpkgbe8apwal22.png)

IAM policy for Lambda so it can access DynamoDB:
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "dynamodb:GetItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DescribeTable"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:dynamodb:eu-west-3:************:table/visitor_count_table"
        }
    ]
}

```
---
#### Policy creation (AWS step 2 of 2): Review and create

- Add a name for the policy (for example 'access_dynamodb_from_lambda')


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ul93lw6hqf43r240ciw9.png)

The Policy should now be created. You can click on the ‘**+/-**’ button on the left of the policy name to view more details.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88uv454keq19stzxgdgx.png)

---

Next, on the left-hand side of the console, click on '**Roles**' and '**Create role**'. Here I'll be attaching the policy to the role. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crcbfzu2f7ugbirqo12d.png)

---

#### Role creation (AWS step 1 of 3): Select trusted entity

On the ‘**Select trusted entity**’ page, select ‘**AWS service**’ and under **Use case** select ‘**Lambda**’, then click on ‘**Next**’


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rujcm7bghfipld0387al.png)

#### Role creation (AWS step 2 of 3): Add permissions
On the ‘**Add permissions**’ screen add the following two permissions by searching for:

- **AWSLambdaBasicExecutionRole**
- **access_dynamodb_from_lambda** (as created in the above step)


Then scroll to the bottom and click ‘**Create role**’


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hi7rypl8q6pufowxo1f7.png)


#### Role creation (AWS step 3 of 3): Name, review, and create

Enter a name for the role (for example:  'lambda_dynamodb_role'), scroll to the bottom and click ‘**Create role**’.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frf3bz06co65lr6skogr.png)

---

## Step 3: Create the AWS Lambda function

In this step I´ll be 1) setting up the Lambda function that will connect to DynamoDB, 2) get a value, 3) perform a calculation and 4) return (replace) it back into the database. Let's get started...

 
- Open AWS Lambda in the AWS console
- Select the region as ‘**Europe (Paris)**’, ‘**eu-west-3’**
- Click on ‘**Create function**’


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adbsrvrp3shk36wpyqsy.png)

In the ‘**Create function**’ section I selected the following:

- ‘**Author from scratch**’
- '**Basic information**'
   - ‘Function name’
      - **Crc_lambda_func_dynamodb_update**
   - Runtime
      - ‘**Python 3.11**’
- **Permissions**
   - Expand ‘**Change default execution role**’
   - Under ‘**Execution role**’, select ‘**Use an existing role**’
   - Under ‘**Existing role**’ locate the IAM role created above, in my case it is ‘**lambda_dynamodb_role**.
- Then click the orange ‘**Create function**’ button at the bottom.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y79wx3tn9j9m57lmapah.png)

When created, the following screen will appear:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rvfavo7knsm2csyfa7xi.png)

---

#### An overview of the Python script

As a reminder the DynamoDB table has been set up like this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ukgirr4jj8jkfj2nugm0.png)

The following Python code that I developed was pasted into the ‘**lambda_function.py**’ file.

```
import json
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('visitor_count_table')

def lambda_handler(event, context):
# The 'event' object contains information from the invoking service
# The 'context' object is passed to your function by Lambda at runtime
    try:
        # 1. Get Item
        response = table.get_item(Key={
                'id':'visitors'
        })
        visitor_count = response['Item']['visitor_count']
        visitor_count += 1
        # timestamp
        date_time = datetime.now()
        str_date_time = date_time.strftime("%Y-%m-%d, %H:%M:%S")
        # print("Current timestamp", str_date_time)
        # 2. Put Item
        response = table.put_item(Item={
                'id':'visitors',
                'visitor_count': visitor_count,
                'timestamp_utc': str_date_time
        })
        return{'Count':visitor_count}
        status_code = response["ResponseMetadata"]["HTTPStatusCode"]
        print("HTTPStatusCode = {}".format(status_code))
        print("Successfully updated - visitor_count now = {}".format(visitor_count))
    except:
        # timestamp
        date_time = datetime.now()
        str_date_time = date_time.strftime("%Y-%m-%d, %H:%M:%S")
        # print("Current timestamp", str_date_time)
        # If the item doesn't exist, create it
        table.put_item(
            Item={
                'id': 'visitors',
                'visitor_count': 1,
                'timestamp_utc': str_date_time
            }
        )
        return{'Count':visitor_count}
        status_code = response["ResponseMetadata"]["HTTPStatusCode"]
        print("HTTPStatusCode = {}".format(status_code))
        print("visitor_count did not exist, recreated, visitor_count now equals: 1")

```
Here is an overview of what it does:

1. Declares that the Lambda function will be working with DynamoDB
2. States the DynamoDB table '**visitor_count_table**'
3. Function:
   - get_item: return the row where 'id' = 'visitors'
      - Declare 'visitor_count' from the DynamoDB table as a variable 
      - Increase the count by 1
      - Put_item:  replace the visitors row with the new value
      - Returns the updated visitor_count value
      - Print the httpstatus code to the console
      - Print confirmation that operation has been performed with new count

---

## Step 4: Create the API Gateway configuration

- Open API Gateway in the AWS console
- Select the region as '**Europe (Paris)**', '**eu-west-3'**
- Click on '**Create API**'
- Choose the API type '**REST API**' and click '**Build**'


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ubuki7da7fwyz4da6rd.png)

---

**Create REST API**
- API details
   - ‘**New API**’ 
- Add an API name 
   -(for example: '**api_lambda_update_visitor_count**')
- API endpoint should be ‘**Regional**’
- Click the orange ‘**Create API**’ button.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xtglaxjkswkn2u39sv4i.png)

**Resources**
- In the ‘**Methods**’ section, click on ‘**Create method**’


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3cqt4tfkylb0ca2txj8.png)

Here I need to create a ‘**GET**’ method that I did with these steps:
- For ‘**Method type**’, select ‘**GET**’
- For ‘**Integration type**’, select ‘**Lambda function**’
- Select the Availability Zone, the same as used for the Lambda function (eu-west-3)
- From the drop down menu, select the Lambda function that we previously created
- Click ‘**Create method**’



![Create method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6730yhhjklxxj6lgaqpq.png)

**Back on the ‘Resources’ Page**
- Open up the ‘**Test**’ tab
- Then click on the orange ‘**Test**’ button
- This should invoke the Lambda function



![Resources Get method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0tody30elf2ylwmbxlq.png)

Checking the DynamoDB table, the visitor_count value should now increment by 1 each time the API is triggered. 


---

## Summary

This was a challenging section to complete, mainly focussed around getting the Lambda function to replace the updated value back into the database. As a result I now have a much better understanding of how this works.

Aside from this, I found it just a simple case of connecting the individual components together.

Next step, connecting the frontend and the backend! 

Thanks for reading!