How to Build Serverless GraphQL and REST APIs Using AWS Amplify

AWS Amplify allows developers to quickly create and connect to powerful services in the cloud. In the previous tutorial, you learned how to set up Amplify in a React project and how to use authentication, S3 storage, and hosting. If you need an introduction to AWS Amplify, be sure to check out that post first.

In this post, we’ll go further with React and AWS Amplify, exploring features like a managed GraphQL data layer and lambda functions.

Adding a GraphQL API

Let’s look at how to add an AWS AppSync GraphQL API to our project and begin using it from within our project.

The API we will create will be a restaurant API for us to keep up with restaurants that we like or would like to visit.

To add the GraphQL API to our project, we can use the following command:

You’ll be prompted to answer some configuration questions. Select the following options:

  • service type: GraphQL
  • API name: TutsGraphQLAPI
  • authorization type: API key
  • annotated GraphQL schema: N
  • guided schema creation: Y
  • What best describes your project? Single object with fields (e.g. “Todo” with ID, name, description)
  • Do you want to edit the schema now? Y

When prompted, update the schema to the following, and then save the file:

This just creates a single data type—Restaurant—with required id and name fields as well as an optional description.

Next, let’s push the updates to our account:

Now, the API has been created!

What just happened here? AWS Amplify used the built-in GraphQL Transform library to create a complete GraphQL API, including additional schema, resolvers, and a data source.

To view the new AWS AppSync API at any time after its creation, you can go to the dashboard at https://console.aws.amazon.com/appsync and click on the API that was just created (be sure that your region is set correctly). From within the AWS AppSync dashboard, you can view the API configuration and perform queries and mutations on the API.

Executing GraphQL Mutations

Next, let’s interact with the API from our React Application.

The first thing we would like to do is create a mutation. In GraphQL, mutations are the equivalent of REST’s PUT, PUSH and DELETE operations. Because we don’t have any data yet in our database, we’ll create a mutation to create a new restaurant item.

To do so, we’ll be importing API and graphqlOperation from AWS Amplify, defining a mutation, and then executing the mutation.

Let’s look at an example app that implements a mutation. In App.js, first we import React, our app CSS, and the necessary AWS Amplify components.

Next, we define a mutation to create a restaurant. We specify that the mutation accepts a name and description and is named createRestaurant. This mutation was defined automatically when we created the Restaurant schema above. Note that the mutation is specified in GraphQL—a domain-specific query language.

Now, we create our app component.

Next, still within the App component, we define a function to execute the mutation. This executes the mutation by calling API.graphql, passing in the mutation and data.

Then we render the component, linking up our change handler and mutation functions.

Finally, we export the App component, with authentication.

You should be able to run this code and begin creating new restaurant items in the API.

To view the actual data source to see if the data is there, open the AWS AppSync dashboard, choose your API, click on Data Sources in the left menu, and then click on the Resource Name. This will open the Amazon DynamoDB table. In the table, you can view the data in the Items tab.

Running GraphQL Queries

Next, let’s look at how to query for data from the API. We’ll implement this in three steps:

  1. define a query
  2. execute the query when the app loads
  3. save the result from the query in our state and render it in the UI

First, let’s define the query in a new component. Once again, we’re using the GraphQL language to specify the query. We’re using the listRestaurants query that was automatically defined when we pushed the Restaurants schema. The snippet below specifies that we’re expecting a list of items, each with an id, name, and description.

Next, we need to add some additional initial state to hold the array of restaurants returned from the server.

We’ll also need to add a componentDidMount lifecycle event to query for data from the GraphQL server. This async method will update the component state when the restaurant list is returned from the server.

Finally, we’ll create a component that maps the restaurants array from the component state to HTML.

Now, when we run the app, we’ll see that the data from the API is being rendered in a list on the screen. However, the app won’t show any changes when the data is updated—for example, when you add a new restaurant. 

So for starters, let’s update the createRestaurant method to provide an optimistic response to the UI. Right now, when we create a new item, the database gets updated, but the UI does not yet know about the new item. To fix this, we’ll update the restaurant array in the createRestaurant method by adding the new item to the array:

Real-Time Data Subscriptions

Next, we want to be able to work with real-time data. In GraphQL, subscriptions allow you to listen for data in real time. When new data is available, the subscription is fired, and the new data is passed down via the subscription. It is up to us on the client side to handle this new data.

In our app, we’ll subscribe to the array of restaurants, and we’ll create an onCreateRestaurant subscription that will fire any time a new restaurant is created. We’ll then take the new item from the subscription, update our existing array, and call setState in order to re-render the UI with the new data.

Just as for mutations and queries, we start by defining the subscription in the GraphQL domain-specific language.

The subscription will be created in the componentDidMount lifecycle method either before or after the GraphQL query we already have set up:

Now, if you open two browser windows, you should be able to create a mutation in one screen and see the update happen on all other screens.

If you look at the .filter method we used in creating the new restaurants array in the subscription, you can see we’re checking to see if there are duplicates that contain both the same name and description. Maybe a better way to do this in production would be to create a unique client ID that is also stored in the database and filter based on that identifier.

Creating a REST API With AWS Lambda

GraphQL is a wonderful cutting-edge technology, but sometimes our project will require that we create a traditional REST API. With AWS Lambda and Amplify, it’s also easy to create serverless REST APIs using the CLI.

When we created the GraphQL API, we used the amplify create api command. This command gives us the option of creating either a GraphQL API or a REST API. The REST API can be configured to use either a standalone serverless Express function or a serverless JavaScript function that is pre-configured to work with Amazon DynamoDB CRUD operations.

The option we will be using for this API is a serverless Express function.

Let’s go ahead and add the new feature:

As usual, this will prompt you to fill in some configuration details. Supply the following options:

  • service type: REST
  • enter a resource name that will be used within the project: e.g. amplifyrestapi
  • enter a path for the REST endpoints: e.g. /people
  • Lambda source: Create a new Lambda function
  • AWS Lambda function name: amplifyrestapifunction
  • function template: Serverless express function (Integration with Amazon API Gateway)
  • edit the local lambda function now? Y

Now, you will be able to edit the lambda function locally. In the file, we’ll replace the existing app.get('/people') method with the following:

This just returns a constant list of names for demo purposes. Save this file, and continue with the following answers:

  • restrict API access? Yes
  • who should have access? Authenticated users only
  • what kind of access do you want for Authenticated users? read
  • add another path? N

This has created a new Lambda function locally that we will be able to update and push to our account as needed. The code for this lambda function is located at amplify/backend/function/amplifyrestapi/src.

Now, let’s push the updates to our account:

Querying the REST API From the Client

Now, our Lambda function is up and running, and we can start interacting with it!

First, let’s query for the data from the new API and show it in our UI. To do so, we’ll be using the API class from Amplify, calling API.get. In the previous section, we used API.graphql to make requests to our GraphQL API, but there are many methods that are available in the API class. You can learn more about the API class in the official docs.

Now, we should be able to run the app, fetch the people data from our API, and render it to the screen.

Updating a Lambda Function From the CLI

In addition to creating a new Lambda function, we can also update our Lambda function from the CLI.

Let’s change the function to hit an API and fetch data instead of hardcoding constants. To do so, we’ll use the axios library for making the HTTP requests, and we’ll fetch data from the Star Wars API.

To use axios, we’ll need to navigate to amplify/backend/function/amplifyrestapi/src and install it there. Axios is installed in the Lambda function’s project folder, not the main app folder, because it is going to be running in the Lambda function server-side.

Now that axios is installed, we’ll update the Lambda function to fetch data from the Star Wars API:

Now, save the file and run amplify push from the main project folder to update your Lambda function in the cloud:

Now, our API is updated and ready to go!

When we refresh the app, we should now see the data that is returned from the Star Wars API.


In this series, you learned how to get started with AWS Amplify and add it to your React project, as well as how to add authentication, storage, hosting, and a GraphQL or REST API—all without having to manually code or provision a server. That’s a lot of power for app developers! 

I hope these posts have inspired you to build your own serverless web apps using serverless technology and AWS Amplify! Let us know what you think in the comments below.

Powered by WPeMatico

Leave a Comment

Scroll to Top