This guide outlines the steps to create a Coffee Shop API using AWS services, Lambda functions, DynamoDB, and API Gateway. The project includes backend functions for managing coffee items (GET, POST, PUT, DELETE), and a frontend React app to interact with the API.
- AWS Lambda (for backend logic)
- AWS API Gateway (for exposing HTTP routes)
- AWS DynamoDB (for storing coffee data)
- Node.js (runtime for Lambda functions)
- React (frontend framework)
- Postman (for testing API)
- AWS CloudWatch (for monitoring and troubleshooting Lambda function execution)
-
Go to the AWS Console → DynamoDB.
-
Create a new table named
CoffeeShop
withcoffeeId
as the partition key. -
Add a new item (coffee) in the table:
{ "coffeeId": "c123", "name": "new cold coffee", "price": 456, "available": true }
-
Create a new IAM role named CoffeeShopRole with the following permissions:
- DynamoDB actions:
PutItem
,DeleteItem
,GetItem
,Scan
,UpdateItem
- CloudWatch logs permissions.
- DynamoDB actions:
-
The policy for this role will look like this:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:PutItem", "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Resource": "arn:aws:dynamodb::<DYNAMODB_TABLE_NAME>" }, { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "*" } ] }
-
Lambda Layer: Create a Lambda layer with the required DynamoDB libraries and common utilities.
-
Create a
nodejs
directory, runnpm init
and install dependencies:npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
-
Create a
utils.mjs
file for shared functions:import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; import { DynamoDBDocumentClient, ScanCommand, GetCommand, PutCommand, UpdateCommand, DeleteCommand } from "@aws-sdk/lib-dynamodb"; const client = new DynamoDBClient({}); const docClient = DynamoDBDocumentClient.from(client); const createResponse = (statusCode, body) => { return { statusCode, headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }; }; export { docClient, createResponse, ScanCommand, GetCommand, PutCommand, UpdateCommand, DeleteCommand };
-
Zip the content of
nodejs
and upload it as a Lambda Layer (layer.zip
).
-
-
Create Lambda Functions: Create Lambda functions for CRUD operations:
getCoffee
,createCoffee
,updateCoffee
,deleteCoffee
.- Attach the
Dynamo-Layer
to each Lambda function.
-
Create API Gateway and add routes for the Lambda functions:
GET /coffee
→getCoffee
functionGET /coffee/{id}
→getCoffee
functionPOST /coffee
→createCoffee
functionPUT /coffee/{id}
→updateCoffee
functionDELETE /coffee/{id}
→deleteCoffee
function
-
Test API: Use Postman to test:
GET /coffee
: Retrieves all coffee items.POST /coffee
: Create a new coffee item.PUT /coffee/{id}
: Update a coffee item.DELETE /coffee/{id}
: Delete a coffee item.
-
React Application:
-
Create a
frontend
directory and run the following commands:npm create vite@latest . npm install npm run dev npm install react-router-dom
-
-
Set API URL:
-
Create a
.env
file in the frontend root and set theVITE_API_URL
to the API Gateway invoke URL:VITE_API_URL=https://<API_GATEWAY_URL>/coffee
-
-
App Structure:
- Update
src/main.jsx
,App.jsx
, andItemDetails.jsx
to reflect the coffee shop UI and integrate the API. - Create a
utils/apis.js
file to handle API requests.
- Update
-
CORS Configuration:
- In API Gateway, go to the CORS settings for
CoffeeShop
and addlocalhost
as the allowed origin. Addcontent-type
to allowed headers, and enableGET
,POST
,OPTIONS
,PUT
, andDELETE
methods.
- In API Gateway, go to the CORS settings for
-
Test the entire setup in Postman:
- Test all CRUD operations:
GET
,POST
,PUT
, andDELETE
endpoints. - Ensure that each operation returns a
200 OK
status.
- Test all CRUD operations:
- Make sure that all the AWS resources (Lambda, API Gateway, IAM Role, and DynamoDB) are in the us-east-1 region.
- Ensure that all Lambda functions have the necessary IAM roles and permissions.
- Use Postman or another API client to thoroughly test the API before deploying it to production.
-
IAM Role Permissions: Configuring the correct IAM permissions for Lambda functions to access DynamoDB and CloudWatch proved challenging. Fine-tuning IAM policies was necessary to ensure proper access rights.
-
CORS Configuration: Properly setting up CORS in API Gateway to enable communication between the frontend and backend(lambda) was cumbersome, particularly when managing different environments (local vs. deployed). Minor misconfigurations often caused issues.
-
Lambda Function Naming and Configuration: Ensuring consistency in naming conventions across Lambda functions, CloudWatch, and zip files was critical. Any mismatch resulted in errors, which were time-consuming to resolve, but CloudWatch logs facilitated troubleshooting.
-
Git Tracking Issues: Git initially failed to track all my folders, especially the
LambdaWithLayer
andfrontend
directories, which led to missing files during commits. I had to manually check and adjust the repository structure to ensure all folders and files were properly added and tracked before pushing. This involved using commands like:
git rm --cached -r LambdaWithLayer frontend
git add LambdaWithLayer frontend
git commit -m "Fix submodule issue and re-add folders"
git push origin main --force