Transforming GraphQL – Infrastructure as Code for Front End Developers

Bookmark

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.



Transcription


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. So my name is Nader Davit. 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 going to 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 static site hosting with a global CDN, kind of really easy to get up and running with Git-based deployments and CICD based on Git projects. We also have a CLI that allows you to, from your front-end application, create and update and modify cloud services using a category-based approach that we'll look at in 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 the 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. 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 going to 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 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, right? But you're also thinking about the maintenance and all 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 going to be diving into on this talk are going to be at model, at auth and at connection. And we're going to 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. 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 the 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 rules. 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 that 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 going to be creating and kind of giving to you out of the box. So 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 want to have the databases for every type. I want to have the resolvers. Also want to map relationships between the different types. And I want to define authorization rules and I want to mock this locally. So let's go ahead and try to do that. So I'm going to go ahead and jump to my terminal. Here in our terminal, we're starting off with the 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 going to do now is add a GraphQL API. So to do that, I'm going to run Amplify add API. This is going to walk us through all the steps. So we're going to choose GraphQL. We're going to give the API a name and we're going to choose a default auth type. For the auth type or authorization type, I'm going to choose Cognito user pool that managed authentication service, but we're going to 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 going to 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, but we don't. So instead, we're just going to choose a guided schema creation and start off with one of the boilerplates that Amplify offers. And I'm going to go ahead and paste in the schema that we're starting off with. And it's going to 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 going to use this GraphQL transform library. First of all, for the at 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. So we don't want to allow anyone else to do any modifications, but we do want to 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 want to 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 its reviews in a single operation. The next thing we'll look at is the review type. And here we have 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 want to 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. We're basically saying if you're signed in, 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 going to 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. So now we can mock this locally before we deploy it by just running amplify mock. And this is going to go back, introspect our schema again, and it's going to go ahead and mock out the product table or the review table. And it's going to generate all of those different resolvers and schema and additional stuff that we'll need. And we can also do local code generation if we were interacting with this API from a JavaScript project. So I'll go ahead and choose yes to all of those questions. And now we have a local graphical server running a local host. So the graphical server is now up and running, and we can now start making operations. So I want to go ahead and update auth to be myself. So I'm going to sign in as dabbit3, generate a token. And what we'd like to do is create a mutation for creating a product. And the product is going to have a description and a name. We're going to 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 want to have a comment, a rating, and we're going to 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. Looks like I don't need some of these fields that are being auto populated. Okay, cool. So we have the fields that we want or 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 the products. And we're going to just going to return all of the products. So 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 able to query products and reviews. We also want to test this out as a public user. 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 dot 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 like I wouldn't recommend doing that because it will cost you around 25 cents 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 like 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 dot cloud. And this is actually running live and you can test it out. And what I 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, this is going to be called Tejas or Natter. And I'm going to say, you know, Tejas or Natter. And this is going to be like maybe who had the better talk or something like that at this event, right? Because Tejas is my friend. This is more of like a friendly thing. What I'd like you to do is go to this or that dot cloud slash Tejas and Natter and vote. And what you should see is if we are opening a couple of tabs at once, you should be able to kind of see the real time updates that are happening here. So if I go ahead and vote Tejas a couple of 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 kind of 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 kind of 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 David3. 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. 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. Because I'm really curious. Yes, let's do it. Can you join me on stage? Yes. Great. I'll start reading the first question for you. From Iraldier, 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 kind of one of those things that you have to take into consideration all the trade-offs, the whole scope of the project when it comes to how much time you're spending developing 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. And 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 going to 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 going to 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. And 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. Yeah, that's a great answer. Thank you so much. Another question was, if Amplify is strictly for AWS? Yes, Amplify is strictly for AWS. It's an open source project. So theoretically, you can use it for other things as well. And some of the front end code, some of the React and JavaScript and client side stuff can actually be used agnostic from any cloud provider. So there's a few features that are in there. But overwhelmingly, the framework is built to support AWS. 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 on my own. So I would love to know what your opinion is on the future of infrastructure as code. Where are we 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, it 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 abstractions. 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'd be docs.awsamplify.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 if there's one thing that people should take away from your talk, what would you like that to be? I think that you're seeing a lot of work out there that makes it easier for people to have like one main skill set. For me, that's kind of like JavaScript and front-end dev and be able to start using it to build more powerful and more full stack applications that we had typically been able to do in the past. So, as a front-end developer, I was really limited to only building out the client side of the app and then other people were building out the services. And I was then in charge of connecting these services. Now what we're seeing is all of these different abstractions like Amplify and other stuff that's out there, Firebase, Netlify, all these players are doing similar stuff. You're able to kind of use your front-end skill set, 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 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. Guys we have a little bit of a cookie team today. I'd love to ask you, are you a bit of a cook? Are you? I can cook one thing and that's 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 the sous chef. You're a sous chef. I'm like the sous chef. Yeah. Great. And 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 like 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 each other in the speaker room. So thank you so much. Thank you for having me. Yes, absolutely. Thank you for having me.
27 min
18 Jun, 2021

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Workshops on related topic