Create a Multiuser GraphQL CRUD(L) App in 5 minutes with the Amplify DataStore

Ed Lima
Open GraphQL
Published in
6 min readJan 22, 2020

A little longer than a year ago I wrote about my experience with the Amplify CLI, just released back then, and how it enabled me to create a multiuser GraphQL CRUD(L) application in minutes. It’s probably a good time to revisit the article and update/refactor my old app to use the recently released Amplify DataStore, taking advantage of its simpler programming model and convenient built-in capabilities as well as getting on with the times and adding React Hooks to the mix.

But what’s the Amplify DataStore and how it can make my life as a developer easier? In case you have some spare time, here’s a great video explaining why the DataStore was created and what problems it’s trying to solve:

In case you don’t have spare time now, save the video for later and keep reading.

The mission if you chose to accept it: create a secure multiuser CRUDL app with even less lines of code and in less time than the app I created last year. How can the Amplify DataStore help?

The Amplify DataStore is a queryable, on-device data store for web, browsers, IoT, and mobile developers developing JavaScript, iOS, Android, and React Native apps. It provides a simple programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data — allowing developers to create rich app experiences.

You can chose to use the DataStore standalone in your application without an AWS account however, when connected to the cloud, it enables very interesting capabilities. With a simple command you can add powerful built-in scalable real-time, offline, versioning, conflict detection and conflict resolution features powered by AWS AppSync and Amazon DynamoDB while still using a simple local-first programming model. Best of all, you don’t even need to know GraphQL to use it. GraphQL is in place behind the scenes acting as a protocol to interact with a flexible and highly available API automatically synchronizing the data to the cloud.

Same as before, in this article we have sample code that will allow you to get started quickly with a very simple CRUD application behind a managed GraphQL API backend. This is just a sample that should be used for learning purposes, it’s not one size fits all and you’ll need to adapt and change for your specific use cases.

In order to get started we’ll need to install and configure the Amplify CLI, and you can do so by following a quick tutorial here. After the CLI is configured with proper AWS credentials, execute the following commands:

$ npx create-react-app notesapp --use-npm
$ cd notesapp
$ npm install aws-amplify aws-amplify-react @aws-amplify/core @aws-amplify/datastore bootstrap
$ npx amplify-app
$ amplify init

Since this is a multiuser application, we need to manage users from a central location or Identity Provider and authenticate them accordingly. Let’s update the API we just created to use a Cognito User Pool that will authenticate and authorize users as required:

$ amplify update api? Please select from one of the below mentioned services: GraphQL
? Choose the default authorization type for the API
Amazon Cognito User Pool
Using service: Cognito, provided by: awscloudformation
The current configured provider is Amazon Cognito.Do you want to use the default authentication and security configuration? Default configuration
Warning: you will not be able to edit these selections.
How do you want users to be able to sign in? Username
Do you want to configure advanced settings? No, I am done.
Successfully added auth resource? Do you want to configure advanced settings for the GraphQL API
No, I am done.

Edit the schema file notesapp/amplify/backend/api/amplifyDatasource/schema.graphql and replace its contents with:

type Note @model @auth(rules: [{ allow: owner }]) {
id: ID!
note: String
owner: String
}

As before we’re taking advantage of the GraphQL Transform useful directives such as @model that will automatically create a DynamoDB table and all the CRUDL logic behind the scenes to store and interact with the data behind an AWS AppSync GraphQL API. We leverage the @auth directive and its ability to easily create simple or complex authorization rules. Notice we added an additional field owner that was not present in the old app, this is needed to authorize real-time subscriptions in the DataStore.

Now use the following commands to generate the data model then commit the changes and start the deployment of the managed serverless cloud resources (GraphQL API and noSQL table):

$ npm run amplify-modelgen
$ npm run amplify-push

The backend services and resources will be configured, linked and deployed following all the AWS best practices:

Services deployed and configured with a “push”

Finally, while CloudFormation is doing its job to create and configure the scalable cloud resources, here’s the last piece of the puzzle. Edit the file src/App.js in the local project and overwrite the content with the following code:

The Code

Time to test! Execute amplify serve or npm start to test it locally then sign up a couple of users with a valid e-mail (you can use the same e-mail for different users) and mobile number, add some new notes and confirm one user has no access to the notes of the other user:

DataStore in action

Users can create, read, update, delete, list and search their own notes in the app interacting with the data directly from the local DataStore. Everything is automatically synchronized with the DynamoDB table in the background. Offline and real-time features are built-in, users can interact with their data when disconnected or automatically get new notes or updates to current notes when connected to different devices.

Locally the data is stored on IndexedDB and can be accessed using the developer tools in the browser. In case on native mobile apps, the data would be stored in SQLite on device. Following a local first programming model, the DataStore is always interacting with local data providing fast performance and a great user experience:

DataStore locally on IndexedDB

It’s not all apples to apples though. The original article used an Elasticsearch cluster to search data, with the DataStore we are using its local querying capabilities. On the other hand, the old app didn’t have any offline or real-time capabilities powered by WebSockets and now this is all integrated in the new app. How about lines of code? The new app has 158 lines of code whereas the old app in its final state had 185 lines of code. Mission accomplished!

The code is available on GitHub. From the repo you can deploy the whole app with 1-click to the Amplify Console (or directly from here), give it a try.

DataStore from Amplify Console

The Amplify DataStore allows developers to focus on their business logic, which is what will truly differentiate their applications. You can interact with local and cloud data interchangeably with simple intuitive commands such as DataStore.save() , DataStore.query(), DataStore.delete(), DataStore.clear() and receive real-time updates with DataStore.observe(). All the complexities of distributed data conflict resolution, real-time, offline and versioning capabilities are handled for you.

--

--

Ed Lima
Open GraphQL

Product Manager AWS AppSync — Working hard. Having fun. Making history. With @AWSAmplify (Opinions. My. Own.)