Building a Serverless Blog Engine with AWS Lambda, API Gateway and DynamoDB

Building a Serverless Blog Engine with AWS Lambda, API Gateway and DynamoDB

I'm excited to introduce a project which I've been working on, and also I'm thrilled to share with you all through this article. It involves " Building a Serverless Blog Engine with AWS Lambda, API Gateway and DynamoDB".

Project Description:-

Building a serverless blog engine with AWS Lambda, API Gateway, and DynamoDB involves creating a scalable, cost-effective, and easily maintainable blog platform. It offers a scalable and cost-effective solution for hosting a blog with minimal infrastructure management.

AWS Services:-

  • AWS Lambda
  • API Gateway
  • Amazon DynamoDB

Services Description:

  • AWS Lambda: AWS Lambda is used to handle the backend logic of the blog, such as creating, reading, updating, and deleting (CRUD) blog posts and comments. Lambda functions are event-driven and scale automatically, making them ideal for handling variable workloads.
  • API Gateway: API Gateway provides a RESTful API that serves as the interface between the frontend of the blog and the Lambda functions. It defines the endpoints for CRUD operations on the blog posts and comments, and it manages the request routing and authentication.
  • Amazon DynamoDB: DynamoDB is a fully managed NoSQL database service provided by AWS. It is used to store the blog posts and comments. DynamoDB is highly scalable, with low latency and seamless scalability, making it suitable for storing and retrieving blog content.

In order to perform these operations, we have to write our backend logic. We will create a Lambda Function for that. Then we build a Blog API using Amazon API Gateway and integrate that with our lambda function. When a user invokes our Blog API, API Gateway routes the request to our Lambda function. The Lambda function interacts with DynamoDB and returns a response to API Gateway. API Gateway then returns a response to the end user.

Article content
Architecture

Procedure to build this blog:-

  1. Steps To Create A Table:-

  • Login your AWS account and go to DynamoDB service. Click upon the “Create Table” button to create a table “blog-database”.
  • For partition key, enter “blogId”.

Article content
Article content

  • DynamoDB also offers a new option regarding the provisioning of read & write capacities: The On-demand mode. Select the Table Settings as Customised Settings and then in Read Write capacity settings, select the capacity mode “On-demand”.

Article content
Article content

  • This mode is great if you have no idea about how much read and write capacity you will need. And you can of course always switch back to fixed limits, too. If you do know which limits make most sense for you, the traditional “in-advance” provisioning will be cheaper.
  • Click on the “Create Table” button at the end. Now, you can see your created table in the Tables tab.

Article content
Article content

2. Steps to create a Lambda Function:-

  • Login your AWS account and go to Lambda Service. Click upon the “Create Function” button to create a lambda function.
  • Select “Author from scratch” and write the function name as “blogapi-lambda” and go with the default settings and hit “Create Function” at the end.

Article content
Article content
Article content

  • Now in the Code Source, you can see a file “index.mjs”. Rename it as “index.js”.

Article content

  • Go to the runtime settings and change the runtime to “Node.js 18.x” and save.

Article content

  • Now replace the contents of index.js with the following code and deploy API.

const AWS = require("aws-sdk"); const dynamoDB = new AWS.DynamoDB.DocumentClient({ region: ‘us-east-1’, apiVersion: ‘2012- 08-10’, }); exports.handler = async (event, context, callback)=>{ if(event.id === undefined){ if(event.httpMethod === "GET"){ // retrieve all blogs from database const params = { TableName: "blog-database" } await dynamoDB.scan(params).promise().then((data)=>{ const restructuredData = data.Items.map((newData)=>{ return ({"blogId": newData.blogId, "title": newData.title, "content": newData.content, "author": newData.author}); }); callback(null, restructuredData); }).catch((err)=>{ callback(err); }) } else if(event.httpMethod === "POST"){ // create a blog in the database const params = { Item: { blogId: "blog_"+Math.random(), title: event.title, content: event.content, author: event.author }, TableName: "blog-database" } await dynamoDB.put(params).promise().then((data)=>{ callback(null, data); }).catch((err)=>{ callback(err); }) } else{ callback(null, Method: ‘${event.httpMethod}’ is not allowed); } } else{ if(event.httpMethod === "GET"){ // retrieve a particular blog from database const params = { Key: { blogId: event.id }, TableName: "blog-database" } await dynamoDB.get(params).promise().then((data)=>{ const restructuredData = { "blogId": data.Item.blogId, "title": data.Item.title, "content": data.Item.content, "author": data.Item.author } callback(null, restructuredData); }).catch((err)=>{ callback(err); }) } else if(event.httpMethod === "PATCH"){ // updade a particular blog in database const params = { Key: { blogId: event.id }, UpdateExpression: set ${event.key} = :value, ExpressionAttributeValues: { ":value": event.value }, TableName: "blog-database", ReturnValues: "UPDATED_NEW" }; await dynamoDB.update(params).promise().then((data)=>{ callback(null, data); }).catch((err)=>{ callback(err); }) } else if(event.httpMethod === "DELETE"){ // delete a particular blog from database const params = { Key: { blogId: event.id }, TableName: "blog-database" } await dynamoDB.delete(params).promise().then((data)=>{ callback(null, data); }).catch((err)=>{ callback(err); }) } else{ callback(null, Method: ‘${event.httpMethod}’ is not allowed); } } }

Article content

  • Your Lambda function is ready to be used. But, by default, no service has any permissions. So, we have to provide this lambda function some permissions to read/write access to DynamoDB. So, go to IAM console and go to Roles section. You can see some roles related to lambda function name. Open the role for your lambda function.
  • There you can find Attach Policies button inside Add Permissions. Click there and add the “AmazonDynamoDBFullAccess” policy.

Article content
Article content
Article content
Article content
Article content

  • Now, lambda function is ready to access DynamoDB.

3. Setup API Gateway:-

Now, we will create our Blog-API. We will use the API Gateway service. Let’s understand what we are gonna create, what will happen behind the scenes of the API---

We will create an API that will have the following routes:

  • /blogs POST to create a blog, GET to fetch all blogs
  • /blogs/:id GET to fetch a particular blog
  • /blogs/:id PATCH to update a particular blog
  • /blogs/:id DELETE to delete a particular blog

To achieve this, follow the steps below —

  • Login your AWS account and go to API Gateway Service. Click upon the “Create API” button and choose REST API (not Private) and click upon the “build” button to create a AWS REST API.

Article content
Article content

  • Let’s create an API of Regional Endpoint. Now our API is created. We just have to define all the HTTP methods our API will react to and all the resources our API will use.

Article content

  • Now create a resource providing resource name & resource path. Here, we are creating a resource with name “blogs” and path “blogs”.

Article content
Article content
Article content

  • Now we have to define the methods (GET, POST etc) we want to handle. So, click on “Create Method” and select the method you want to define. I am selecting GET to retrieve all blogs. Now there are some API Integration Types (which kind of action you want to execute whenever a request hits this resource). We will select Lambda Function and from all the lambda functions, we have to choose that lambda function we created earlier i.e. “blog-api-lambda”. Now, save it.

Article content
Article content
Article content

  • Now, inside the Integration Request, go to Mapping Template and check “When there are no template defined(recommended)” and create a mapping template with “application/json‘ and generate template using “Method Request Passthrough”. You can replace all commands with the following code & save the code. Yeah! GET request on /blogs route will now be handled by our lambda function.

{

"httpMethod": "$context.httpMethod"

}

Article content
Article content
Article content
Article content

Similarly, create the following API Resources and Methods —

  • POST in /blogs: This is same as previous, just at the body template, use the following code:

#set($inputRoot = $input.path('$'))

{

"httpMethod": "$context.httpMethod",

"title" : "$inputRoot.title",

"content" : "$inputRoot.content",

"author" : "$inputRoot.author"

}

Article content
Article content

  • GET in /blogs/{id}: For these type of request handling, we need to create a new Dynamic Resource with parameter id. So, create a dynamic resource providing resource name & resource path as id and {id} respectively. Now, your dynamic resource is created. Just handle the GET request same as previous. Just, in mapping template use the following code:

{

"httpMethod": "$context.httpMethod",

"id" : "$input.params().path.id"

}

Article content
Article content
Article content

  • PATCH in /blogs/{id}: Create a PATCH method to handle the update blogs query using PATCH method in /blogs/{id} route which is same as previous. Just use the following code in the mapping template:

#set($inputRoot = $input.path('$'))

{

"id" : "$input.params().path.id",

"httpMethod": "$context.httpMethod",

"key" : "$inputRoot.key",

"value" : "$inputRoot.value"

}

Article content
Article content
Article content

  • DELETE in /blogs/{id}: Create a DELETE method to handle the delete blogs query using DELETE method in /blogs/{id} route which is same as previous. Just use the following code in the mapping template —

{

"id" : "$input.params().path.id",

"httpMethod": "$context.httpMethod"

}

Article content
Article content
Article content
Article content

  • Finally, all the resources & methods will look like the image given below. We just need to deploy our API now. Just click upon the “Deploy API” button. Fill the stage name, description as given below and click on “Deploy”.

Article content
Article content

  • Congrats!! Your blog-api is now live.

4. Testing our Blog API:-

  • Make a POST request on /blogs route with the following JSON:
  • { “title”: “Deploy your React Application on AWS”, “content”: “This is the content for my first blog”, “author”: “Arindam Halder”}

Article content
Article content

  • Make a GET request on /blogs route, you can see all blogs.

Article content

  •   Make a GET request on /blogs/{id} route, you can see the particular blog.

Article content

  • Make a PATCH request on /blogs/{id} route with the following JSON:

{

“key”: “author”,

“value”: “arindam369”

}

Article content

  • Make a DELETE request on /blogs/{id} route, the blog will be deleted.

Article content

I sincerely thank to My faculty mentor Dr.Kavitha Sadam mam.


The code in your lambda section does not copy & paste well and had at least 1 issue that prevented it from working. One thing, for certain, that would make that a more straightforward lift & shift would be to use encapsulated comments /* like this */ instead of the unterminated version // like this. I'm going back through everything again at the moment as it's all there, and all wired up, but isn't working. Still, happy for the headstart this article provided.

To view or add a comment, sign in

More articles by BURADAGUNTA CHANDAN CHAITANYA

Others also viewed

Explore content categories