DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Unlocking the Benefits of a Private API in AWS API Gateway
  • Building a Scalable ML Pipeline and API in AWS
  • Container Checkpointing in Kubernetes With a Custom API
  • Serverless NLP: Implementing Sentiment Analysis Using Serverless Technologies

Trending

  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks
  • The Full-Stack Developer's Blind Spot: Why Data Cleansing Shouldn't Be an Afterthought
  • Integrating Model Context Protocol (MCP) With Microsoft Copilot Studio AI Agents
  • Metrics at a Glance for Production Clusters
  1. DZone
  2. Data Engineering
  3. Databases
  4. A Simple API Using AWS RDS, Lambda, and API Gateway

A Simple API Using AWS RDS, Lambda, and API Gateway

Let's use a host of AWS tools—RDS, Lambda, and API Gateway—to create a simple API that can scale on your cloud deployment.

By 
Kin Lane user avatar
Kin Lane
·
Nov. 11, 17 · Tutorial
Likes (5)
Comment
Save
Tweet
Share
35.0K Views

Join the DZone community and get the full member experience.

Join For Free

I wrote about a simple API with AWS DynamoDB, Lambda, and API Gateway last week. I like this approach because of the simple nature of AWS DynamoDB. One benefit of going this route is that you can even bypass Lambda, as the AWS API Gateway can work directly with AWS DynamoDB API. I’m just playing around with different configurations and pushing forward my understanding of what is possible, and this week I switched out the database with AWS RDS, which opens up the ability to use MySQL or Postgres as the backend for any API.

For this example, I’m using a simple items database, which you can build with this SQL script after you fire up an RDS instance (I’m using MySQL):

CREATE TABLE `items` (
  `item_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`account_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


Next, I wanted to have the basic CRUD operations for my API. I opted to use Node.js running in Lambda for the code layer of this API, starting with the ability to get all records from the database:

var mysql = require('mysql');

exports.handler = function(event, context) {

        var connection = mysql.createConnection({
            host: '[rds_host]',
            user: '[rds_user]',
            password: '[rds_password]',
            database: '[rds_database]'
        });

        connection.query('SELECT * FROM items', function(error, results, fields) {

            context.succeed(results);
        });


After that, I want to be able to insert new records:

var mysql = require('mysql');

exports.handler = function(event, context) {

    var connection = mysql.createConnection({
        host: '[rds_host]',
        user: '[rds_user]',
        password: '[rds_password]',
        database: '[rds_database]'
    });

    sql = "INSERT INTO items(name)";

    sql = sql + " VALUES('" + event.name + "')";

    connection.query(sql, function(error, results, fields) {

        response = {};
        response['item_id'] = results.insertId;
        response['name'] = event.name;

        context.succeed(response);
    });
}


Then, of course, be able to get a single record:

var mysql = require('mysql');

exports.handler = function(event, context) {

    var connection = mysql.createConnection({
        host: '[rds_host]',
        user: '[rds_user]',
        password: '[rds_password]',
        database: '[rds_database]'
    });

    sql = "SELECT * FROM items WHERE item_id = " + event.item_id;

    connection.query(sql, function(error, results, fields) {

        context.succeed(results);
    });
}


Then be able to update a single record:

var mysql      = require('mysql');

exports.handler = function(event, context) {

  var connection = mysql.createConnection({
    host     : '[rds_host]',
    user     : '[rds_user]',
    password : '[rds_password]',
    database : '[rds_database]'
  });

  sql = "UPDATE items SET ";

  sql = sql + "name = '" + event.name + "'";

  sql = sql + " WHERE item_id = " + event.item_id;

connection.query(sql, function (error, results, fields) {

  response = {};
  response['item_id'] = event.item_id;
  response['name'] = event.name;

  context.succeed(response);

  });
}


And of course I want to be able to delete records:

var mysql = require('mysql');

exports.handler = function(event, context) {

    var connection = mysql.createConnection({
        host: '[rds_host]',
        user: '[rds_user]',
        password: '[rds_password]',
        database: '[rds_database]'
    });

    sql = "DELETE FROM items WHERE item_ID = " + event.item_id;

    connection.query(sql, function(error, results, fields) {

        response = {};
        response['deleted'] = event.item_id;

        context.succeed(results);

    });
}


Now that I have the business logic set up in AWS Lambda for reading, and writing data to my relational database I want an API front-end for this backend setup. I am using AWS API Gateway as the API layer, and to set up, I’m just importing an OpenAPI definition to jumpstart things:

swagger: '2.0'
info:
  title: "Item API"
  description: "This is a simple API"
  termsOfService: "https://example.com/tos/"
  contact:
    name: API Evangelist
    url: https://apievangelist.com
    email: info@apievangelist.com
  license:
    name: Need a License for Interface
    url: http://example.com/license/
  version: v1.2
host: example.com
basePath: /
schemes:
  - http
produces:
  - application/json
paths:
  /items:
    get:
      summary: Get Items
      description: Returns items.
      operationId: getItems
      responses:
        '200':
          description: Item Response
          schema:
            type: array
            items:
              $ref: "#/definitions/item"
        '500':
          description: Error Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
      tags:
        - Items
      x-lambda-script: /lambda-scripts/get_items/index.js
    post:
      summary: Add Item
      description: Add item.
      operationId: addItem
      parameters:
        - in: body
          name: body
          schema:
            $ref: '#/definitions/item'
      responses:
        '200':
          description: Item Response
          schema:
            type: array
            items:
              $ref: "#/definitions/item"
        '500':
          description: Error Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
      tags:
        - Items
      x-lambda-script: /lambda-scripts/create_item/index.js
  /items//{item_id}/:
    get:
      summary: Get item.
      description: Returns a single item
      operationId: getItem
      parameters:
        - in: path
          required: true
          type: string
          name: item_id
          description: The item id.
      responses:
        '200':
          description: Item Response
          schema:
            type: array
            items:
              $ref: "#/definitions/item"
        '500':
          description: Error Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
      tags:
        - Items
      x-lambda-script: /lambda-scripts/get_item/index.js
    put:
      summary: Update item.
      description: Updates an item.
      operationId: updateItem
      parameters:
        - in: path
          required: true
          type: string
          name: item_id
          description: The item id.
        - in: body
          name: body
          schema:
            $ref: '#/definitions/item'
      responses:
        '200':
          description: Item Response
          schema:
            type: array
            items:
              $ref: "#/definitions/item"
        '403':
          description: No Access Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
        '500':
          description: Error Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
      tags:
        - Items
      x-lambda-script: /lambda-scripts/update_item/index.js
    delete:
      summary: Delete item.
      description: Deletes an item.
      operationId: deleteItem
      parameters:
        - in: path
          required: true
          type: string
          name: item_id
          description: 'The item id.'
      responses:
        '200':
          description: Contact Response
          schema:
            type: array
            items:
              $ref: "#/definitions/item"
        '403':
          description: No Access Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
        '500':
          description: Error Response
          schema:
            type: array
            items:
              $ref: "#/definitions/error"
      tags:
        - Items
      x-lambda-script: /lambda-scripts/delete_item/index.js
definitions:
  item:
    description: The developer item.
    properties:
      item_id:
        description: 'The id for the item.'
        type: string
      name:
        description: 'The name of the item.'
        type: string
  error:
    description: 'Describes an HTTP error returned'
    properties:
      code:
        description: 'Repeat the HTTP status code'
        type: integer
      message:
        description: 'A plain language message explaining the error'
        type: integer


This gives me the skeleton framework for my API, with the paths and methods I need to accomplish the basics of reading and writing data. Now, I just need to wire up each API method to its accompanying Lambda function, something API Gateway makes easy.

Now I have an API for my basic backend. There is one thing you have to do to make each method work properly with the Lambda function. You have to set up a body mapping to the item_id when passed in the path for the PUT, GET, and DELETE functions. If you don’t the item_id won’t be passed on to the Lambda function — it took me a while to get this one.

There are other things you have to do, like setting up a usage plan, turning on API key access for each API, and setting up custom domain if you want, but hopefully this simple gets the point across. I will work on other parts in future posts. Hopefully, it provides a basic example of an API using RDS, Lambda, and API Gateway, which is something I have wanted to have in my toolbox for some time.

The process has opened my eyes up wider to the serverless world, as well as playing more with Node.js — which has been on my list for some time now. It provides a pretty solid, scalable, manageable way to deploy an API using AWS. I have all the code on GitHub and will be evolving as I push it forward.

If you apply the Lambda scripts, make sure you upload individually as zipped files so that the MySQL dependencies are there, otherwise the script won’t connect to the database. It should provide a base template you can use to seed any basic data API. This is why I’ve added it to my API Evangelist toolbox, giving me a simple, forkable set of scripts I can use as a seed for any new API. I will add more scripts and templates to it over time, rounding off the functionality as I evolve in my understanding of deploying API using AWS RDS, Lambda, and API Gateway.

API AWS

Published at DZone with permission of Kin Lane, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Unlocking the Benefits of a Private API in AWS API Gateway
  • Building a Scalable ML Pipeline and API in AWS
  • Container Checkpointing in Kubernetes With a Custom API
  • Serverless NLP: Implementing Sentiment Analysis Using Serverless Technologies

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!