Building a Serverless API with AWS Lambda and DynamoDB

Building a Serverless API with AWS Lambda and DynamoDB

Introduction

In this tutorial, we're going to build a serverless API using AWS Lambda and DynamoDB. Serverless computing allows you to build and run applications and services without thinking about servers. AWS Lambda lets you run your code without provisioning or managing servers, and DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.

Prerequisites

To follow along with this tutorial, you should have:

  • An AWS account.
  • Basic understanding of JavaScript and Node.js.
  • AWS CLI installed and configured on your local machine.
  • Basic understanding of AWS services, especially AWS Lambda and DynamoDB.

Step 1: Set Up Your AWS Lambda Function

1.1. Log in to your AWS Management Console. Navigate to the Lambda service. Click on «Create function».

1.2. Select «Author from scratch», give your function a name, and select the Node.js runtime. Click «Create function».

Step 2: Create a DynamoDB Table

2.1. Navigate to the DynamoDB service in the AWS Management Console. Click «Create table».

2.2. Give your table a name and define the primary key. Click «Create».

Step 3: Write Your Lambda Function

Now, we need to write the code that our Lambda function will execute. We'll create a simple API that creates, reads, updates, and deletes items from our DynamoDB table.

3.1. Navigate back to your Lambda function. In the Function code section, delete any existing code and replace it with the following:

  1. // Import AWS SDK
  2. const AWS = require('aws-sdk');
  3.  
  4. // Create new DynamoDB instance
  5. const dynamo = new AWS.DynamoDB.DocumentClient();
  6.  
  7. exports.handler = async (event) => {
  8. let body;
  9. let statusCode = 200;
  10. const headers = {
  11. "Content-Type": "application/json"
  12. };
  13.  
  14. try {
  15. switch (event.routeKey) {
  16. case "POST /items":
  17. // Code for creating an item
  18. break;
  19. case "GET /items":
  20. // Code for getting all items
  21. break;
  22. case "GET /items/{id}":
  23. // Code for getting a specific item
  24. break;
  25. case "PUT /items":
  26. // Code for updating an item
  27. break;
  28. case "DELETE /items/{id}":
  29. // Code for deleting an item
  30. break;
  31. default:
  32. throw new Error(`Unsupported route: "${event.routeKey}"`);
  33. }
  34. } catch (err) {
  35. statusCode = 400;
  36. body = err.message;
  37. } finally {
  38. body = JSON.stringify(body);
  39. }
  40.  
  41. return {
  42. statusCode,
  43. body,
  44. headers,
  45. };
  46. };

This is a basic setup for our Lambda function. It doesn't do anything yet, but it's prepared to handle different routes and HTTP methods for our API.

Step 4: Implement CRUD Operations

This is where we implement the code for creating, reading, updating, and deleting items from our DynamoDB table. We'll do this in the switch statement in our Lambda function.

4.1. Implement the «POST /items» route:

  1. case "POST /items":
  2. // Code for creating an item
  3. body = await dynamo.put({
  4. TableName: "my-table",
  5. Item: JSON.parse(event.body),
  6. }).promise();
  7. break;

In this code snippet, we're using the `put` method of our `dynamo` instance to create a new item in our DynamoDB table. The item data comes from `event.body`. 4.2. Implement the «GET /items» route:

  1. case "GET /items":
  2. // Code for getting all items
  3. body = await dynamo.scan({ TableName: "my-table" }).promise();
  4. break;

Here, we're using the `scan` method to get all items from our table.

4.3. Implement the «GET /items/{id}» route:

  1. case "GET /items/{id}":
  2. // Code for getting a specific item
  3. body = await dynamo.get({
  4. TableName: "my-table",
  5. Key: {
  6. id: event.pathParameters.id
  7. },
  8. }).promise();
  9. break;

In this case, we're using the `get` method to fetch a specific item identified by its `id`. The `id` is obtained from `event.pathParameters.id`.

4.4. Implement the «PUT /items» route:

  1. case "PUT /items":
  2. // Code for updating an item
  3. body = await dynamo.update({
  4. TableName: "my-table",
  5. Key: {
  6. id: JSON.parse(event.body).id
  7. },
  8. UpdateExpression: "set info = :x",
  9. ExpressionAttributeValues: {
  10. ":x": JSON.parse(event.body).info
  11. },
  12. ReturnValues: "UPDATED_NEW"
  13. }).promise();
  14. break;

For updating an item, we use the `update` method. We use an `UpdateExpression` to specify the attribute we want to update, and `ExpressionAttributeValues` to specify the new value for the attribute.

4.5. Implement the «DELETE /items/{id}» route:

  1. case "DELETE /items/{id}":
  2. // Code for deleting an item
  3. body = await dynamo.delete({
  4. TableName: "my-table",
  5. Key: {
  6. id: event.pathParameters.id
  7. },
  8. }).promise();
  9. break;

Finally, we use the `delete` method to delete a specific item.

Step 5: Deploy and Test Your API

5.1. Save your Lambda function and navigate to the API Gateway service in the AWS Management Console.

5.2. Create a new HTTP API. Connect it to your Lambda function and define the routes and methods according to your Lambda function handler.

5.3. Deploy your API and make note of the invoke URL.

5.4. You can now use tools like Postman or curl to send requests to your API and see the responses!

Conclusion

Congratulations! You've built a serverless API using AWS Lambda and DynamoDB. You've learned how to create, read, update, and delete items in a DynamoDB table from a Lambda function, and how to set up an HTTP API with API Gateway. This foundation can be used to build more complex serverless applications in the future. Happy coding!

We use cookies to improve your browsing experience. By continuing to use this website, you consent to our use of cookies. Learn More