VOOZH about

URL: https://thenewstack.io/build-a-serverless-api-with-aws-gateway-and-lambda/

⇱ Build a Serverless API with AWS Gateway and Lambda - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2020-09-01 15:00:46
Build a Serverless API with AWS Gateway and Lambda
contributed,sponsor-thundra,sponsored,sponsored-post-contributed,
API Management / Observability / Serverless

Build a Serverless API with AWS Gateway and Lambda

In this article, we explain general API implementation concepts using AWS Lambda and other AWS services.
Sep 1st, 2020 3:00pm by Serkan Özal
👁 Featued image for: Build a Serverless API with AWS Gateway and Lambda
Feature image via Pixabay.
Thundra sponsored this post.
APIs are a crucial part of any web application and there are different techniques for development and design. Serverless is one approach gaining popularity, because of its cost-efficiency, scalability and relative simplicity. As a leading serverless provider, Amazon Web Services (AWS) has made a huge contribution to the world of serverless development, and in this article, we will explain general API implementation concepts using AWS Lambda and other AWS services.

Why AWS Lambda?

Serkan Özal
AWS Lambda is an AWS service that is responsible for running particular functions in response to particular triggers — events happening in the application. Those triggers could be HTTP calls; events from other AWS services like S3, Kinesis, or SNS; or just recurrent scheduled events. Functions are executed in some type of ephemeral containers, which are fully provisioned and scaled by AWS, so the development team can focus more on the code and functionality than on infrastructure. Another attractive feature is the pay-as-you-go payment model, where you are charged only for the total execution time of your functions and do not pay for idle time. Of course, like any other service, Lambda has limits and is sometimes not suitable for certain tasks — such as very long-running jobs, heavy computing jobs, or processes that require control over the execution environment. However, AWS Lambda usually works perfectly for implementing APIs.

The Role of API Gateway

AWS API Gateway is a service allowing developers to create and manage HTTP endpoints, map them to particular AWS resources, and configure custom domains, authorizing mechanisms, caching and other features. API Gateway is the fundamental part of serverless API, because it is responsible for the connection between a defined API and the function handling requests to that API.
Thundra Foresight empowers developers to build successful CI pipelines by providing deep analytics and debugging capabilities. With observability into the CI process, Thundra Foresight helps optimize build duration, enable more frequent deployments, increase productivity, and lower CI costs.
Learn More
The latest from Thundra

HTTP APIs

As mentioned, API Gateway includes a lot of functionality and integrations. At some point, though, Amazon realized that serverless developers usually do not require all of those features, but instead need a general simplification of the implementation process. That is probably why in late 2019, AWS announced the new HTTP APIs, a lite version of API Gateway, which dramatically simplifies the developer experience and provides better performance and lower costs for serverless APIs. Although it is simple, HTTP APIs still support such important features as configuring CORS for all endpoints, JWT integration, custom domains and VPC connections.

Understanding Serverless API Concepts

In order to easily understand the main concepts of serverless API implementation, we’ll build a very minimalistic example of a simple “virtual whiteboard” application, consisting of two simple endpoints: POST for writing messages on a whiteboard, and GET for fetching the three most recent messages. We will also consider other possible features — like path parameters, CORS, and authorizers — but we’ll keep the final implementation simple and clear to read.

AWS DynamoDB

We will make our project completely serverless, by using AWS DynamoDB for storing messages. This database corresponds to serverless principles, is easy to use, and offers a pay-per-request model that is really cost-effective. DynamoDB is a NoSQL key-value database offered by AWS, where your data is stored across AWS servers and fully managed by Amazon.

AWS Serverless Application Model

In order to continue further implementation, you’ll need an AWS account and AWS Serverless Application Model (SAM) installed and configured. SAM is a tool for creating, updating, and managing serverless applications and all the resources needed for the application to operate. With AWS SAM, you don’t need to create every single service manually via web console, but just to describe all the things needed in the special template file. After you’ve installed the CLI, navigate to the directory you are going to work in and run this command:
$ sam init -r nodejs12.x -n whiteboard
Initializing new project Select the first option, then select “Quick Start from Scratch.” This will create a “whiteboard” directory with a minimum of setup files inside.

Define the Required Resources Needed

First, open the template.yml file and remove everything below the “Resources” section. Before moving to the API itself, let’s create the secondary resources. Define a DynamoDB table where messages will be stored:
Resources:

 BoardMessagesTable:
 Type: AWS::DynamoDB::Table
 Properties:
 TableName: board-messages-table
 AttributeDefinitions:
 - AttributeName: partKey
 AttributeType: S
 - AttributeName: createdAt
 AttributeType: N
 KeySchema:
 - AttributeName: partKey
 KeyType: HASH
 - AttributeName: createdAt
 KeyType: RANGE
 ProvisionedThroughput:
 ReadCapacityUnits: 5
 WriteCapacityUnits: 5
Declaring DynamoDB table The code above will tell AWS to create a DynamoDB table, where attribute “partKey” will be a partition key that is the same for all records and “createdAt” will be a range key, allowing further sorting by timestamp. We may also add other keys and values into the records, but you are not required to define those. Now, in the same file, just below the previous definition, declare the HTTP API to which all future endpoints and functions will be related.
BoardHttpApi:
 Type: AWS::Serverless::HttpApi
 Properties:
 StageName: Test
 CorsConfiguration: True

Declaring HTTP API The definition is very small and simple since we just included the stage name and CORS configuration, which are not actually required either. This illustrates how simple and clean API creation can be. However, there are many possible properties to add, such as a reference to authorization function, definition of the domain to use, logging settings, and others.

Define API Handlers Functions

Finally, when we have the API defined, let’s also declare two functions connected to its particular endpoints.
PostMessageFunction:
 Type: AWS::Serverless::Function
 Properties:
 Handler: src/handlers/postMessage.handler
 Runtime: nodejs12.x
 MemorySize: 128
 Timeout: 5
 Events:
 PostMessage:
 Type: HttpApi
 Properties:
 ApiId: !Ref BoardHttpApi
 Method: POST
 Path: /messages
 Policies:
 - AmazonDynamoDBFullAccess

 GetMessagesFunction:
 Type: AWS::Serverless::Function
 Properties:
 Handler: src/handlers/getMessages.handler
 Runtime: nodejs12.x
 MemorySize: 128
 Timeout: 5
 Events:
 GetMessages:
 Type: HttpApi
 Properties:
 ApiId: !Ref BoardHttpApi
 Method: GET
 Path: /messages
 Policies:
 - AmazonDynamoDBFullAccess

Declaring handlers for POST and GET requests The above code is quite self-descriptive: two functions, one of which will be invoked upon a POST request to the “/messages” path, and the other of which will be invoked upon a GET request to the same path. Both functions have a capacity of 128 MB RAM and a five-second timeout. The functions’ code is found in the postMessage.js and getMessage.js files under the /src/handlers/ directory. We are going to create those right now. (Note that we’ve provided full access to the DynamoDB in the “Policies” section of each function, just to make things easier.) In a real project, you should consider providing more granular access.

Coding the Functions

Navigate to the /src/handlers directory and create files there with the following content: postMessage.js
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB();

exports.handler = async (event) => {
 const { body } = event;
 try {
 const { author, text } = JSON.parse(body);
 if (!author || !text) {
 return {
 statusCode: 403,
 body: 'author and text are required!'
 }
 }

 await dynamodb.putItem({
 TableName: 'board-messages-table',
 Item: {
 msgId: { S: 'board' },
 author: { S: author },
 text: { S: text },
 createdAt: { N: String(Date.now()) } // still expects string!
 }
 }).promise();
 return {
 statusCode: 200,
 body: 'Message posted on board!',
 }
 } catch (err) {
 return {
 statusCode: 500,
 body: 'Something went wrong :(',
 }
 }
};
POST request handler’s code This function will run in response to POST requests and will parse the author and text of the message from the request body and save that data into the database. It also fills the “partKey” attribute with the same value for all records. Although usually this is not a good practice, it is completely fine for this example, as it allows you to sort by range key among all items with the same partition key. Note that DynamoDB always expects string data to be saved, even if the type of attribute is a number. getMessages.js
const AWS = require('aws-sdk');
const dynamodb = new AWS.DynamoDB();

exports.handler = async () => {
 try {
 const result = await dynamodb.query({
 TableName: 'board-messages-table',
 KeyConditionExpression: 'partKey = :partKey',
 ScanIndexForward: false,
 Limit: 3,
 ExpressionAttributeValues: {':partKey': { S: 'board'}}
 }).promise();

 return {
 statusCode: 200,
 headers: {
 'Content-Type': 'application/json',
 },
 body: JSON.stringify(result.Items),
 }
 } catch (err) {
 console.log(err);
 return {
 statusCode: 500,
 body: 'Something went wrong :(',
 }
 }
};
GET request handler’s code In this function we first get records with “partKey” equal to “board,” then use “ScanIndexForward” set to “false” to sort messages so that the most recent is first, and finally we use the “Limit” property to limit results to three messages.

Deployment

Deployment with AWS SAM is easy and can be done with a single command and a few inputs. Navigate to the root directory of the project and run the following command:
$ sam deploy --guided
Deployment command You will then be asked to enter the name of your app and the AWS region to use. You’ll also need to confirm some actions:
👁 Image

Fill in and accept settings

After you’ve completed all the confirmations, deployment will start, and you’ll see all the resources being created. This takes about a minute or less.
👁 Image

List of resources to be created and their statuses

When the process is finished, open the AWS web console in your browser, navigate to API Gateway service, find the newly created API, and copy the URL to the root endpoint of your API.
👁 Image

URL to API root endpoint

Testing the API

Let’s create a few messages on the board using the default “curl” tool. Use the following command, but replace placeholders with your own data.
curl -d '{"author":"name", "text":"Message text"}' -H "Content-Type: application/json" -X POST https://your-api-id.execute-api.your-region.amazonaws.com/test/messages
Performing POST request with curl Send a few different requests with different messages. If everything is OK, you’ll see “Message posted on board!” in the console without any errors. In order to fetch the last messages, run an even shorter command:
curl https://your-api-id.execute-api.your-region.amazonaws.com/test/messages
Performing GET request with curl Congratulations! You’ve just built a simple HTTP API with AWS Lambda and AWS SAM. Of course, in a real project you would use additional features and configurations, but the principles remain the same: define resources, define configurations, write the code, and run deploy.

Connect Thundra Monitoring

It’s very good practice to have monitoring set up — especially for serverless applications, as they are really tricky to debug and trace. Connect Thundra monitoring to the newly created Lambda functions (see the quick start guide). Once you’ve connected Thundra, you’ll need to instrument the “postMessage” and “getMessages” Lambda functions in order to see detailed information about every single invocation and have a global picture of your application. Select functions in the list and click the “Instrument” button, then confirm instrumenting by clicking “OK.”
👁 Image

Confirm Lambda function instrumenting

Try to make a few other requests to your API, then return to the Thundra dashboard, click on the function’s name, and select any of the invocations in the invocations list. You’ll see details about timing, performance, function inputs and outputs, etc. This can be extremely useful in debugging APIs in real-life projects.
👁 Image

Details about a single invocation

If you or your company use serverless in complex projects with different AWS or third-party services integrated, you should definitely consider using the unique tracing feature, which will dramatically simplify application troubleshooting and debugging.

Are HTTP APIs Worth Using?

HTTP APIs plus AWS Lambda is a great way to build performant and cost-effective APIs. Although it is actually a lite version of API Gateway REST APIs, it still provides all the needed functionality and covers 90% of developers’ needs. HTTP APIs don’t support some useful features, like caching, schema validation and response transformations. Caching, though, is probably not something you’ll need, as HTTP APIs are much faster then the old REST APIs, and validation and transformations can be done at the function’s code level. If your development team has no other reason to refuse to use HTTP APIs, you may confidently proceed to development with this great feature. Usually, the journey of a serverless transaction starts with an API call and it can be daunting to trace an asynchronous flow of events. Thundra comes to the rescue for such issues, with its end-to-end distributed tracing feature. Thundra is free up to 250K requests per month, which can be quite useful for small projects or startups. If you’d like to gain full observability through serverless APIs, sign up for Thundra today.
Thundra Foresight empowers developers to build successful CI pipelines by providing deep analytics and debugging capabilities. With observability into the CI process, Thundra Foresight helps optimize build duration, enable more frequent deployments, increase productivity, and lower CI costs.
Learn More
The latest from Thundra
TRENDING STORIES
Serkan Özal is co-founder and CTO of Thundra. He has 10+ years of expertise in software development, is an AWS Certified PRO and has a patent on distributed environments. He mainly works on serverless architectures, distributed systems and monitoring tools.
Read more from Serkan Özal
Thundra sponsored this post.
SHARE THIS STORY
TRENDING STORIES
Amazon Web Services is a sponsor of The New Stack.
TNS owner Insight Partners is an investor in: Pragma.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.