In this talk I’ll show how we can use a combination of GraphQL SDL along with a new DSL (GraphQL Transform) created the Amplify team to build out a full stack cloud application directly from your GraphQL schema. Using this GraphQL DSL, we’ll walk through how to model a Database, authorization rules, relationships, and custom access patterns. We’ll look at how to rapidly prototype an example application, and view some demos including a voting app capable of handling over 100,000 operations per second.
Transforming GraphQL – Infrastructure as Code for Front End Developers
AI Generated Video Summary
This talk is about building full-stack cloud applications as a front-end developer using GraphQL and the GraphQL Transform library. It covers the three main parts of AWS Amplify: hosting, CLI, and client libraries. The GraphQL Transform library simplifies building a GraphQL API by handling schema creation, database interaction, and resolver mapping. It demonstrates how to use GraphQL transforms to build a GraphQL API with features like authorization rules, relationships, and local mocking. It also discusses the considerations for using managed services and the future of infrastructure as code with Amplify and other tools.
1. Introduction to Transforming GraphQL
This talk is about how to build full-stack cloud applications as a front-end developer. It's broken up into four parts. We'll cover data modeling using GraphQL and the GraphQL transform library, do a live demo of rapid prototyping, and showcase a real application built with GraphQL transforms.
Okay. Well, hello, everyone. Welcome to my talk. This is transforming GraphQL, full-stack infrastructure as code. And this talk is about how to build full-stack cloud applications as a front-end developer. It's broken up into four parts. We're going to do an introduction into some of the content that I'm going to be talking about. We're going to walk through how to do data modeling using GraphQL and the GraphQL transform library. We're going to then do a live demo of some rapid prototyping. And then I'm going to show you a live example of one of the applications that I've built using these GraphQL transforms.
2. Introduction to AWS Amplify and Full Stack Cloud
This part introduces the speaker, Nader David, who is a software engineer and author. He works as a developer advocate on the AWS Amplify team, focused on building full stack cloud tooling and SDKs. The talk will cover the three main parts of Amplify: hosting, CLI, and client libraries. The CLI workflow involves initializing a project, adding or updating features, and deploying updates. Amplify provides cloud infrastructure and local infrastructure as code.
So my name is Nader David. I am a software engineer. I'm also an author, and I've done a lot of open source and other things. And right now I work as a developer advocate on the AWS Amplify team. The latest book that I have out is called Full Stack Serverless. And it's really closely tied to some of the stuff we're talking about today. It's available from O'Reilly. So if you're interested in some of the stuff I'm talking about, I would definitely recommend checking out that book.
So the team that I work on, I mentioned before, is AWS Amplify team. And we are focused on building full stack cloud tooling and SDKs. And one of our main focuses is around new developers into the cloud ecosystem, front-end developers, and also just around improving the DX of a lot of the stuff that AWS traditionally had done a lot differently. So some of the different infrastructure that people would like to use are the same things that are running these massive companies at scale. So Netflix, Airbnb, even Amazon are using a lot of the services that our team is trying to build easier abstractions on top of. And that's at the core of some of the stuff I'm gonna be talking about with the GraphQL Transform Library.
So when I say full stack cloud tools and SDKs, exactly what am I talking about? Well, I'd like to first start by breaking down Amplify and talking about what Amplify is. Amplify is really made up of three main parts. We have the hosting that has a static site hosting with a global CDN, kind of really easy to get up and running with, and get based deployments and CI, CD, based on get projects. We also have a CLI that allows you to, from your front end application, create an update and modify cloud services using a category-based approach that we'll look at just a moment. And then after you create the services via the CLI, we have a client that is, we have different clients actually for iOS, Web, React Native, and we also have framework specific components within these client libraries that allow you to interact with those services after you've created them.
So what does the CLI workflow look like? It's something like this. You initialize a new project by running Amplify Init. You add a new feature or you update a feature by running Amplify add or Amplify update. And when you're ready to deploy any updates, you just run Amplify push. And then after that, you can make additional updates by running Amplify update. And then after you've created these services, you import the components or the different libraries from AWS Amplify. So in this example, we have storage, and then you're able to then make calls against your storage service or your API service or whatever service you're working with. So really what we're talking about here when we talk about full stack cloud is you're using this CLI and you're getting two different types of, I guess, artifacts from that. You get the cloud infrastructure and then you get the local infrastructure as code. And also you get additional other local code for things like authentication flows and different UI components that we also include in our client libraries. But really the main part we're really talking about today is the cloud infrastructure and the infrastructure as code part.
3. Introduction to GraphQL Transform Library
We'll be focusing mainly on GraphQL. The GraphQL Transform library simplifies building a GraphQL API from scratch. It handles schema creation, database interaction, and resolver mapping. Services like AWS AppSync make building APIs easier. The GraphQL transform library uses directives to add configuration and features. We'll dive into the at model, at auth, and at connection directives, which scaffold databases, resolvers, CRUD operations, and subscriptions.
So what are some of the categories that we enable right now? Well, within each of these categories, there's typically a couple of different services. So for instance, for API, you can create a REST API, a couple of different types of those, or a GraphQL API. So we support all of these different features, but we're really gonna be focusing mainly on GraphQL today.
And the GraphQL Transform library is part of some of the tooling that the CLI gives you. And what exactly is the GraphQL Transform library? Let's first kind of take a look at that before we dive into some of the more, the deeper understandings of what exactly this library does. So let's talk about building a GraphQL API from scratch. What would you need to make this happen? So let's say you needed a to-do app and you needed a way to create, update, and delete to-dos. You would first start off with your GraphQL schema and the schema might have a to-do type. You would then create, update, and delete mutations. You might also have a query for getting a to-do and listing all of the to-dos. And then you might have subscriptions that you would create for on create, on update, and on delete to-do. So you would need to create all that schema. You would then need to have some type of database or data source that would interact with your GraphQL API. And then you would need to create the resolvers that map between the schema with the GraphQL operations and the data sources.
So putting all this together is quite a bit of work, but on top of that, you have to think about stuff like authorization, authentication, security, anything that may be vulnerable as far as a GraphQL API is concerned, things like nested queries and things like that. So when you're building an API, you not only are thinking about your infrastructure, but you're also thinking about the maintenance and all of this additional code that you're dealing with. So services like AWS AppSync, which is a managed GraphQL service kind of make this easier. And that's essentially what powers the GraphQL transform library under the hood. So using these directives, we can take the managed GraphQL service that is AppSync, use our local GraphQL schema with Amplify and add a bunch of different new pieces of configuration, but also different features and stuff just by using these directives.
So here's some of the ones that we enable right now, and the ones we're gonna be diving into on this talk are gonna be at model, at auth and at connection. And we're gonna look exactly like what are those doing. So when you're working with the GraphQL transform library, like how does this actually work? Well, just think of a typical GraphQL schema. You just write all of the schema definition that you would need. With the GraphQL transform library, you would then decorate your base types with these different directives. And then you run a build. And then after you run that build, we generate infrastructure as code. And then when you run the deployment, we deploy that infrastructure for you based on those directives.
So let's look in a little more depth at some of these directives. So at model is really one of the most powerful ones. And this directive scaffolds out databases, resolvers and CRUD operations and subscriptions really for any base type.
4. Building API with GraphQL Transforms
In this part, we explore how to use GraphQL transforms to simplify the process of building a GraphQL API. We discuss the at model directive for generating a DynamoDB table and the associated CRUD operations and subscriptions. We also cover the at auth directive for implementing different authorization rules, including public and private access. Additionally, we introduce the at key directive for configuring additional data access patterns. The challenge for this talk is to build an API using GraphQL transforms in just a few minutes, including the schema, databases, resolvers, relationships, authorization rules, and local mocking.
So for instance, we need an e-commerce application. All we need to do is create this base type of product and the at model directive will generate a DynamoDB table. It'll generate, create, read, update, delete operations for the product. We'll also create subscriptions for own, create, own, update and own, delete, and then we'll generate all of the resolvers that map between the GraphQL operations and that data source. So you run a build and this is kind of what you get, those three things that I just mentioned.
We also offer a way to put and model different authorization rules around a type. So for instance, let's say we have this type of post and you might think of a blog or something like that and using the at auth rule and passing in the allow owner property, we're essentially saying, okay, only the owner of this post can update or delete or even read this post, but more likely, you might have a combination of different roles. So for instance, if you think of a blog or even think of something like Instagram or Twitter, you typically have a combination of a couple of different types of authorization. Those two types are typically both a combination of public and private. So using this combination of rules here, we allow owners to create update and delete. And then after the operation has been successful and you've created or updated or deleted a post, then anyone can actually read the post. So we have that public access for reading, private access for updating and deleting. And then you can add additional rules there as well. So think about things around maybe admin privileges and stuff like that. And then we also have the at key directive that allows you to configure additional data access patterns across your different types. So think of an application again, maybe something like an e-commerce app where you have an inventory type. By default you can get an inventory piece by ID, you can list all of the inventory, but that's all we create by default. Using the at key directive, we can add additional data access patterns. We can do stuff like get by warehouse ID, get by within an inventory amount range, we can get within a price range. And by doing, to kind of set that up, all we need to do is specify the field that we'd like to query on, and then the query field, which is the GraphQL query that we're gonna be creating and kind of giving to you out of the box.
What is the challenge that I would like to do for this talk? Well, I'd like to go ahead and take these GraphQL transforms and build out an API in just a couple of minutes. And what I'd like to do is I'd like to build this API in about five minutes. It needs to have a fully mapped out schema based on a couple of base types. I wanna have the databases for every type, I wanna have the resolvers, also wanna map relationships between the different types, and I wanna define authorization rules, and I wanna mock this locally. So let's go ahead and try to do that. So I'm gonna go ahead and jump to my terminal. Here in our terminal, we are starting off with a basic Amplify project that has authentication enabled via Amazon Cognito User Pools, which is a managed authentication service, something like Auth0. And what we're gonna do now is add a GraphQL API. So to do that, I'm gonna run amplify-add-api. This is gonna walk us through all the steps.
5. Choosing GraphQL and Auth Type
We choose GraphQL, specify the API name, and select a default auth type, Cognito User Pool. We add an additional auth type for public access. Advanced settings allow us to add more auth types, and we choose API key for public access. We set an expiration and choose no for conflict detection. Offline support can be enabled, and we can reference an existing local schema if available.
So we're gonna choose GraphQL, we're gonna give the API name, and we're gonna choose a default auth type. For the auth type or authorization type, I'm gonna choose Cognito User Pool that managed authentication service, but we're gonna add an additional auth type for public access in just a moment. For advanced settings, I'll choose yes so we can add that additional auth type. And I'm gonna choose API key for public access. Give it an expiration. Choose no for conflict detection. If we wanted offline support, we would choose yes. If we had a schema that we wanted to kind of start off with and we had it already created locally, we could reference that.
6. Schema Creation and Authorization Rules
We choose a guided schema creation and start with an Amplify boilerplate for an e-commerce app with product and review types. Using the GraphQL transform library, we create CRUD operations, subscriptions, resolvers, and tables for products and reviews. Admins have full access to create, update, and delete products, while public and private access is allowed for reading. We establish a one-to-many relationship between products and reviews, enabling queries by product and combined product and review queries. For reviews, admin and owner access is allowed, along with public and private reading access. After saving and compiling the schema, we can mock and generate the necessary resources locally.
But we don't. Instead, we're just gonna choose a guided schema creation and start off with one of the boilerplates that Amplify offers. And I'm gonna go ahead and paste in the schema that we're starting off with, and it's gonna be kind of like an e-commerce app where we have a product type and we have reviews. And people can create a product if you're an admin and you can leave reviews if you're just a user.
So to get this actually working, we're gonna use this GraphQL transform library first of all for the app model directive to go ahead and create CRUD operations and subscriptions and resolvers and a product table and a review table for each of these two different types. So then we'll be able to create, read, update, delete products and reviews, and we'll also be able to map subscriptions to those. We also use this at auth type to go ahead and define a few authorization rules. The first thing we're doing for the product type is we're saying that admins have full access to create, update, and delete products. But we don't wanna allow anyone else to do any modifications. But we do wanna allow both public and private access for reading. So that means if a user is signed in or if they're just visiting the site, they're able to read products.
The next thing we have is this add connection directive on the review type, that's, I mean, on the product type for the reviews array. And what this basically does is we're basically saying we wanna have a one to many relationship between one product and many reviews. And therefore, when we create a review, we can define which product we're reviewing. And then we're able to query reviews by product. We're also able to query both the product and each reviews in a single operation.
The next thing we'll look at is the review type. And here we have a similar rules, but we have actually maybe a little bit more going on here where we're allowing admin access for everything. We're also allowing owner access because we wanna say that anyone can create a review and they can also update or delete their reviews if they would like. We're having public access for reading reviews and also private access for reading reviews or basically saying, if you're signed in or if you're not signed in, you can still read reviews. And then we can go ahead and save this and jump back to our command line because that's really all we need to do. And this is gonna introspect our schema, make sure it's valid. And then if it is, it should give us a message saying it's been compiled successfully.
7. Creating Products, Reviews, and Querying
I update the auth to be myself and create a mutation for creating a product. We get unauthorized because we are not signed in as an admin. We mock ourselves as an admin and test the create product operation. Next, we create a comment or review with a comment, rating, and product ID. We update our auth to be a different user and try creating the review. Finally, we query all products and their reviews as a sign-in user and test it as a public user.
So I wanna go ahead and update off to be myself. So I'm gonna sign in as debit three, generate a token. And what we'd like to do is create a mutation for creating a product. And the product is gonna have a description and a name. We're gonna go ahead and create this. And boom, we're getting that unauthorized because we are not signed in as an admin. So our authorization rules are working so far. Let's go ahead and mock ourselves as an admin and test this out. Now that we're an admin, we should be able to create this operation. So the create product is successful.
Next, let's go ahead and create a comment or a review. So for the create review, we'll go ahead and say, we wanna have a comment, a rating and we're gonna need to specify the ID of the product. So we'll leave that product ID there. The comment is, awesome shoes. And let's go ahead and update our auth and say that we are now a different user. And it looks like I have some stuff going on here. It looks like I don't need some of these fields that are being auto-populated. OK, cool. So we have the fields that we want are Comment, Product Reviews, ID, and Rating. So I should be able to go ahead and try this out. We are able to do this since we are just a typical sign-in user. So we've created our review.
And then finally, we want to, I guess, for now, let's stay signed in as this user. And we want to go ahead and query all of the products. And we're just going to return all of the products. But we now have this relationship between products and reviews. So we can actually pull the reviews for a product. So let's go ahead and pull all of that and run this query. And there you see that we, as a sign-in user, are able to query products and reviews. We also want to test this out as a public user.
8. Building a Scalable Voting App
We've created a basic application with authorization rules and deployed it locally in just a few minutes. If we want to deploy it to our back-end services, we can run Amplify Push. I'll show you an example of a voting app called this-or-that.dev, which is highly scalable. I've tested it with millions of operations and it worked perfectly. However, it can be costly, so keep that in mind. The schema includes poll and candidate types, authorization rules, and at-key directives for additional data access patterns. You can create a poll, add candidates, and allow voting. You can try it out live at this-or-that.cloud.
So we're going to now be signed in or signed out. And we're just kind of mocking public access. We see that that still works. So we've created this basic application with authorization rules, everything deployed in just a few minutes locally. And we can go back. And if we'd like to deploy this to our back-end services, we can run Amplify Push.
So that's kind of it on that part. So let's go back to my slides. And I have a couple of examples. But I'm only going to show one now. This is a voting app that I built. And this is a very, very scalable voting app. And it's called this-or-that.dev. I've actually tested this out with a few million operations over the course of a minute. And everything scaled and worked perfectly. I would say I wouldn't recommend doing that, because it will cost you around $0.25 or something like that per million operations. So think about that. But just testing it out, it will scale. It will get to that point. I'm just going to show you the schema that I worked with. So I have a poll type. And I have a candidate type. I have a few authorization rules. And I have a few at-key directives that allow additional data access patterns. But essentially you create a poll. Then you create a candidate for that poll. And then you allow voting on that poll. So to test this out, I'm going to go ahead and open my browser and go to this-or-that.cloud. And this is actually running live. And you can test it out.
9. Creating a Poll and Conclusion
I'd like to create a new poll called Tejas or Natter, where people can vote on who had the better talk. Visit this-or-that.cloud/Tejas or Natter to vote and see real-time updates. Share the poll with others. Thank you for attending my talk. Find me on Twitter at Davit3 for any questions or assistance.
And what I'd like to do is create a new poll. And I want everyone here at this talk to test this thing out. So I'm going to say that this is going to be called Tejas or Natter. And I'm going to say Tejas or Natter. And this is going to be maybe who had the better talk or something like that at this event, right? Because Tejas is my friend. This is more of a friendly thing.
What I'd like you to do is go to this-or-that.cloud slash Tejas or Natter and vote. And what you should see is if we are opening a couple of tabs at once, you should be able to see the real time updates that are happening here. So if I go ahead and vote Tejas a couple times, I come back here and vote Natter. You see that it comes through in real time. And then if you'd like to share this, you can copy that to your clipboard and share it and be on your way.
So yeah, this will be fun. So I'm looking forward to seeing the votes on this when people start jumping in. And that's about it for this talk. So thank you for checking out my talk. You can find me on Twitter at Davit3. If you have any questions, I'd love to answer them at the Q&A here, or afterwards if you have any questions a week from now, a month from now, reach out to me on Twitter. I'd be glad to help. And that's it. So thank you so much for coming to my talk.
Considerations for Managed Services
It's important to consider the trade-offs, project scope, development time, maintenance costs, and pricing when deciding between using a managed service or building from scratch. Managed services offer the advantage of someone else taking ownership of code and security, but may come at an extra cost. Evaluate your domain expertise, team, and total cost of ownership before making a decision.
Wow, Natter. That was such a good talk. Thank you so much for enlightening all of us. We have some questions that came in. So let's switch to the questions, shall we? Let's do it. Cheers. Yes, let's do it. Can you join me on stage? Yes. Great. I'll start reading the first question for you. From Iradir, is the combination of hard to predict prices versus, say, a monthly fee for normal hosting, plus the vendor lock-in issue is something that's keeping me away from it. How can I make sure that in six months from now, I'm not paying multiple dollars a month, or I'll have to take my app down? Yeah, that's a really popular question. It's a really good question, really. I think it's one of those things that you have to take into consideration all of the trade-offs, the whole scope of the project when it comes to how much time you're spending developed building some of these features, the maintenance costs, and the actual pricing. So let's say that you are taking advantage of a managed service, not just from AWS, but really from any cloud provider or any managed service provider, you can think of things like Auth0 or Cloudinary, AWS, GCP. We all have our own versions of these things. Let's say you wanted to kind of roll your own authentication from scratch as opposed to maybe using AWS authentication service or some authentication service. How much time are you gonna spend building that from scratch? How much experience do you have in that domain? All of these things kind of come into play. And when you start thinking of the total cost of ownership, building all this, making sure it's secure, making sure that when your application scales, it continues to be secure. The hours that you might spend doing that or even hiring other people to come build those things for you, that's the real trade off there. So you're gonna pay extra typically for some type of managed service or even a cloud service. But what you're getting in return is kind of someone else taking ownership of all of that code, taking ownership of the security concerns. And at the end of the day, a lot of times, it just makes more sense to use one of these cloud services. But other times, it does make more sense to build it yourself. So I would say, I wouldn't always say to go with the cloud service. I would say, look at your domain expertise, look at your team, look at the total cost of ownership, then make that decision.
Amplify, Infrastructure as Code, and Key Takeaway
Amplify is strictly for AWS, but some front-end code can be used agnostic from any cloud provider. The future of infrastructure as code is heading towards better and more concise abstractions. Abstractions like Amplify and serverless framework make it easier for front-end developers to build scalable systems without deep knowledge of low-level infrastructure. To learn more, check out the Amplify documentation and explore Serverless Framework and Terraform. The key takeaway from this talk is that these tools enable developers to have a single main skillset.
Yeah, absolutely. I want to remind everyone that Discord is still open. I'm still checking. So if you have any questions for neither, just let me know or let everybody of us know, actually. I have some questions of my own. So I would love to know what your opinion is on the future of infrastructure as code, where we're heading. I think we're heading more and more to better and more understandable and cleaner and more concise abstractions on top of infrastructure as code. If you kind of look at any distributed system that people are actually building right now in the wild anyway, most of those are actually built on top of infrastructure as code, but to actually understand how to implement a complex system and how to understand how to put all the pieces together takes a lot of domain expertise and takes a lot of knowledge, it takes a lot of time to gain that knowledge. And I think what you're seeing is these abstractions like Amplify, but there's other stuff out there as well, where people are kind of allowing you to use more concise language, better things like serverless framework is a good example, where they kind of built a more concise version of infrastructure as code, where you're kind of still writing infrastructure as code, but it's less code and you have to know less about the underlying services. And then Amplify is even a higher level on top of that, where you're just running commands that have to do with categories as opposed to the actual service names and how everything works together. I think you're going to see more and more stuff around that. I think that a lot of people are realizing the power of infrastructure as code, but they're also realizing how complicated it is really to kind of build at the very low level. So they're making it easier for people like me, who is traditionally a front-end developer, be able to kind of build out these scalable systems on these really powerful platforms without having to spend five years understanding how all of the low-level stuff works just by providing these better abstraction.
Yeah, wonderful. And if there's people who want to learn more about this, where do you recommend they would start? I mean, if you're looking to learn more about Amplify in general, I would definitely check out the docs. So it would be docs.awsamplify, I believe, .com. We have a new section of guides that's going to be released at the end of the month that kind of dives deep and provides a lot of in-depth tutorials. But right now, all the documentation is there for all of the different APIs that we support and stuff like that. If you're looking to learn more about infrastructure as code in general, I would definitely also check out Serverless Framework. I would check out Terraform, which allows you to write code across all cloud providers, so not just AWS. And those three would be pretty much the things that I would definitely check out if you're interested.
Super cool, okay. And then what is, if there's one thing that people should take away from your talk, what would you like that to be? I think that, you know, you're seeing a lot of work out there that makes it easier for people to have like one main skillset.
Now, what we're seeing is all of these different abstractions like Amplify and other stuff that's out there, you know, Firebase, Netlify, all these players are doing similar stuff. You're able to kind of use your front-end skillset, but you're now also able to write the backend part without understanding all of the bits and pieces that go into putting all this stuff together. We're just giving, we're getting these APIs that we can consume and that we can control using the domain knowledge that we already have.
Yeah. All right. Thank you for that. As we have a little bit of a cookie team today, I'd love to ask you, are you a bit of a cook better, are you? I can cook one thing and that's a grill, anything on the grill, I can cook that. Other than that, my wife is an amazing cook. So I just support her in the kitchen, I go to the grocery store, buy stuff and clean up and do all of the support stuff. Like she's the expert and I'm very lucky. I'm like the sous chef, yeah.
Great, and what is then, what's your favorite comfort food? I would say anything with carbohydrates because I don't really eat a lot of carbs. So whenever I get the chance to, I really eat 10 times more than I probably should. Wow, okay, well that's, okay. Thank you for sharing that with us. And thank you so much again for your talk. I think we're going to move to a little break, but first of all, I want to make sure that everybody knows that they can still continue to talk to Nader in the speaker room. So thank you so much for joining us. Thank you for having me, yes.