How to GraphQL – A Fullstack Tutorial for GraphQL

(howtographql.com)

276 points | by evo_9 10 days ago

12 comments

  • ulkesh 10 days ago

    What’s really missing is that every single GraphQL tutorial glosses over the server. Sure there’s a chapter on it. A whole chapter.

    There are no good articles on server best practices, how best to use ORM with it (especially as it relates to lazy loading), etc.

    While we are going full board with GraphQL, we’re having to really fly by the seats of our collective pants because practical GraphQL serving is a far cry from idiomatic GraphQL. Some of us have more complicated applications than NEWHOPE, EMPIRE, and JEDI.

    • schickling 10 days ago

      This is a fantastic point!

      Co-creator of How to GraphQL here. I’m very excited to tell you that we’re currently working on a new iteration of the page and content that will include more in-depth chapters about dataloaders, authentication, authorization and other advanced topics.

      Would be great to hear more thoughts on which topics you’d like to see covered.

      • pjmlp 9 days ago

        For me to even start thinking about GraphQL instead of REST, there needs to exist Java, .NET and C++ mature libraries for GraphQL at the same level of available REST ones.

        Using JavaScript ones is not an option. So that is the kind of thing I would care about.

        • monch1962 9 days ago

          I would add Python and Go to that set of required, mature server-side libraries.

          If there's solid libraries for each of the common languages used to write serverless code, then I think that'd be a big plus for decision makers who are on the fence about adopting GraphQL

          • pjmlp 9 days ago

            Sure, I was only listing the ones from my toolbox. :)

        • e12e 9 days ago

          I've yet to go beyond a cursory skim of graphql - but my first impression is that in the end you get to write your very own query planner/optimizer - with the "benefit" of optimizing across wildly different data stores like unifying a few different sql databases, a few filsystem graph/hierarchies of meta-data and a handful of semi-structured document stores in the form of json/soap services... So a lot harder than the already pretty hard problem of writing a query planner for "just" an rdms.

          But I think there's something "there" - graph dbs, datomic, web prolog - they all seem to point to clients asking a "what" with the server figuring out the "how" [ed: and not in the least: whence (from where)] .

        • JasonSage 10 days ago

          I think there are actually a few reasons for this that are addressable.

          GraphQL clients cover a ton of the functionality—so much so that you're more concerned about the basic concerns you're already familiar with: doing stuff with your data.

          The server has the inverse problem. A GraphQL server library covers the low-level part of breaking down the query into actionable slices, but how you resolve those is more of an open-ended problem. And because there's such a variety of ways you could be fetching that data, it's hard for the server library to steer the implementer in any one direction. Every server is going to be vastly different, while every client is going to use very similar patterns.

          • adamkl 10 days ago

            Very true. In our case, we resolve queries against some pretty old legacy SOAP/XML services, so topics like selectively loading fields from databases and dataloaders don’t enter into our equations.

            I thinks it important to remember that GraphQL should form a very thin layer of an application stack. I gave a 4 hour intro lesson at my employer and the bulk of it was not GraphQL, but how we resolve GraphQL against our specific backend data sources.

          • tomnipotent 10 days ago

            > how best to use ORM with it

            GraphQL is not about the server-side - that's an implementation detail and is orthogonal to GraphQL itself. I think it's important that we don't conflate ORMs with GraphQL just because an ORM can be used to simplify the server-side implementation (take a look at Graphene [1] or Prisma [2]).

            [1] https://github.com/graphql-python/graphene [2] https://github.com/prismagraphql/prisma

            • joshwa 9 days ago

              > GraphQL is not about the server-side - that's an implementation detail and is orthogonal to GraphQL itself.

              And yet. Somebody has to be there to parse GraphQL and turn those queries into database or other external calls--and do so efficiently--for a large/combinatoric number of potential variations of entity graphs.

              • d_watt 9 days ago

                Isn't that the same as REST? Using that stops at the controller for the request, and then it's up to the sever how it wants to fulfill requests for entities.

                • ulkesh 9 days ago

                  The difference is that REST is more opinionated on the server for what gets returned, and how it is returned. With GraphQL, that power is in the client request. And allowing the client to dictate the full scope of data to be loaded on the server can cause some problems depending on how complex the data model is.

                  This is why we are going to surface the more complex children of certain models as root queries instead. It’s considerably less than ideal from an idiomatic GraphQL point of view, but it’s much more practical. If data models are simpler, then GraphQL works great. Or if the data model is flat, it works great. Anything else and it’s not as cut and dry.

                  • joshwa 8 days ago

                    It's less a criticism of GraphQL-the-specification and more a matter of GraphQL-the-community failing to provide any reference implementation for the most basic of usecases--the 95+% of apps that use ORMs.

                    That said, GraphQL-the-spec does highlight a key ORM weakness--it's not so easy to dynamically construct complex join queries with decently-optimized fetch plans.

                • ulkesh 10 days ago

                  I’m referring to the fact that if you don’t directly use the ORM models as the model being returned in the GraphQL response, and instead use a DTO, in order to not have to eagerly load everything you would have to deep inspect the GraphQL request selections to determine just how much data to load. I don’t find it quite as orthogonal as some.

                • erpellan 6 days ago

                  GraphQL seems only slightly more sensible than exposing your SQL interface to the internet.

                  Yes it makes sense from a client-side / front-end perspective, but that's because the server is just a [handwave]. Someone else's problem.

                  • matchagaucho 9 days ago

                    From a 3-tier architecture perspective, when I hear "GraphQL is better than REST", I immediately think middleware replacement.

                    Took me a minute to grok that this comparison implicitly depends on a Graph DB server.

                    If I were writing a book, I would probably start by explaining use cases where graphs are a better data structure... then advance to query concepts.

                    • lolive 9 days ago

                      GraphQL is to expose data. REST to expose services.

                      • ulkesh 9 days ago

                        Can you explain the difference?

                        I’ve written many RESTlike APIs (no hypermedia) and they mostly returned data. In fact, the whole premise is to be able to access resources which typically boils down to some data model response.

                        • lolive 8 days ago

                          Disclaimer: I come from the Semantic Web area. Where the client language is SPARQL, and the (graph) database is exposed publicly and understands SPARQL. The data are exchanged in RDF (a kind of JSON for graph data).

                          A SPARQL query can federate data from several SPARQL endpoints (this is all the point of the LinkedData movement).

                          So we have NO additional layers between the DB and the client (except for some security features, and query throttling)

                          This is a simple pattern that makes data access trivial. (if you manage to store your data in such a graph database, which is NOT trivial)

                          As far as I understand, if you follow a similar philosophy, then GraphQL will shine too (especially because the tooling on the client-side is infinitely superior with GraphQL, than it is with SPARQL).

                          But the more I read this HN thread, the more it seems GraphQL is used for service integration. And that is a completely different problem.

                          So, I feel like data access with GraphQL is super nice. (especially if you use best practices for your data, like in the LinkedData principles) But service integration sounds yet another hell. (because services are rarely designed to be properly integrated together).

                          • ulkesh 7 days ago

                            I completely understand now where you’re coming from. Thing is, we’re taking an existing data model that has REST in front of it (a layer or two up), and trying to instead use GraphQL. I think, though anecdotal for me, that this is the more typical use case since most won’t be able to re-engineer the database to be more conducive to GraphQL.

                            And I think this now makes some sense as to why there is hardly any documentation with respect to practical GraphQL and ORM (in the vein of Spring Boot and Hibernate for us old Java folk).

                            Thanks for the explanation!

                  • adamkl 10 days ago

                    Just a disclaimer here, and I don't want to ruffle any feathers, but this tutorial has been put together by the graphcool/prisma team and promotes the use of their Prisma GraphQL/ORM/Database product.

                    I've used some of their tools (and I am even working on a library that would be a good compliment to Prisma), but don't come out of this tutorial thinking that Prisma is some sort of defacto standard back-end for GraphQL APIs.

                    • augbog 10 days ago

                      yup great point thanks for calling that out. I appreciate they made their tutorial free though.

                    • Azeralthefallen 10 days ago

                      I recently moved one of our API's from Loopback to GraphQL using Postgraphile. It has been a nightmare.

                      - Access restrictions, and security is very painful. Trying to enforce RBAC through postgresql policies over hundreds of tables with slightly different policies is a nightmare. Hiding all this on the DB's end and burying this stuff in migrations sucks for anyone trying to develop on it.

                      - I still have not found a good solution to querying/filtering over things like nested JSONB objects without writing my own resolver functions, which then complicates numerous things.

                      - Versioning is a mess, especially when you don't have an easy way to force clients to upgrade (i.e. mobile apps), along with other parties using your graphql api directly.

                      - However the worst thing so far to me has been i have watched as UI developers go from writing simple rest queries, and doing a bit of work on the front-end to writing extremely inefficient and convoluted queries. Even worse is when a third party is doing it and i have no say over what they do with it.

                      • hn_throwaway_99 10 days ago

                        Oh god, this sounds like a nightmare. I posted this in another story on GraphQL, but it is now clear to me that GraphQL is being used in ways that make it a disaster, and part of the problem is that there are tools (sounds like Postgraphile) that encourage this misuse.

                        My thoughts on the issue:

                        - Perhaps GraphQL's biggest mistake is using "QL" in the name. GraphQL is NOT AND SHOULD NOT be a replacement for SQL, and that's where I think folks get confused. Whenever I see complaints about "I can't do joins, and GraphQL is missing generic filter statements" I'm sure people are totally missing the point of GraphQL.

                        - Your last bullet point (about UI developers going from writing simple rest queries to convolute front end queries) made me extremely sad, as when done right this is where GraphQL truly excels. Where I've used GraphQL to great success is to define my types to very closely match what the UI developers need. In fact, I have the UI devs themselves write the type and query definitions, code reviewed by backend engineers. This makes it trivial for UI devs to code against, for example, a mocked up version of the APIs while backend devs build out the resolvers.

                        The issue is that GraphQL is GREAT as a layer BETWEEN your lower level data sources and backend APIs and your front end, and the "translation layer" is done in the resolvers. This is especially true for native clients when you may have multiple versions of clients in the wild.

                        • acjohnson55 9 days ago

                          Amen. GraphQL is neither a query language, nor particularly graph-oriented, IMO. It's a framework for building APIs. It's comparable to a really full featured hypermedia framework. I'm a huge fan, but the marketing is definitely confusing.

                        • adamkl 10 days ago

                          This just sounds like you are missing required layers of your application.

                          I haven't used Postgraphile, but it sounds like you are just exposing your database directly out through a GraphQL wrapper. You'd be experiencing the same pain if you tried this approach with any API technology (gRPC, REST, SOAP, etc).

                          You should still have code for authorization and business logic, and your API should probably be exposing a focused subset of your data model unless your clients really need to be able to traverse the entire database.

                          • Azeralthefallen 10 days ago

                            Except utilizing loopback i simply define my models, what fields are exposed by models, and their relationships. I can easily implement RBAC restrictions via a simple access hook or ACL's.

                            To me having to maintain two separate graphql services for a single API seems extremely convoluted. I can't expose the private api to any other internal services, because all the authorization and restrictions are done on the application layer.

                            To me isn't that just using a GraphQL server as an ORM? To me that seems like an extremely roundabout way to do something like that.

                            • adamkl 10 days ago

                              Well, Postgraphile is offering you a shortcut that comes with limitations.

                              A more complete approach would be to structure your application in a more typical fashion, and put a GraphQL layer on top. Have a data access layer that maps from our back end sources (databases/REST/RPC services) to GraphQL types. Then have a logic/authorization layer, with GraphQL on top. Using Postgrapile seems to take those application layers away for the sake of convenience.

                              • tomnipotent 10 days ago

                                > because all the authorization and restrictions are done on the application layer.

                                Which application tier? It sounds like you're using GraphQL in-memory to query the database in the same process that's creating the GraphQL query. You should be treating GraphQL as a database, and it should not exist on the same machine that's using it. This way your GraphQL app has centralized permissions & auth, and all your other apps would then be beholden to whatever you implemented.

                                > just using a GraphQL server as an ORM

                                If you're using it the way above, then yes. But that's the wrong way to use it.

                            • sorenbs 10 days ago

                              Co-author of the tutorial and founder of prisma here.

                              Adamkl is right, you are missing a layer in your application. postgraphile, prisma and hasura turn your database into a graphql api, but you don't want to expose that directly. Graphql Bindings allow you to construct a Graphql Api by mapping an existing Api and implementing extra logic.

                              This allows you to keep permission and business logic in your application layer where it belongs.

                              My Co-founder Johannes is giving a talk on this technique at GraphQL Europe on Friday. The talks will be available online shortly after, so I would recommend keeping an eye out for that if you are not going.

                              • Azeralthefallen 10 days ago

                                So basically you are running two graphql services, and using the private one as an ORM?

                                Doesn't that drastically increase complexity in the fact that you now need to maintain multiple services? Why not just skip postgraphile and just use an ORM in your business layer? As opposed to being required to maintain multiple services.

                                It also feels very odd that since you can't even expose your private one to other internal services because all your authorization and access restrictions are now sitting in your business layer, which to me seems like a huge waste.

                                • sorenbs 10 days ago

                                  Correct, you are running at least two separate GraphQL APIs.

                                  If you look at the architecture of modern tech companies they are already moving in this direction. Facebook has TAO for data access, and twitter has Strato: https://about.sourcegraph.com/graphql/graphql-at-twitter/ The purpose of these data services is to enable feature developers to focus on their feature instead of worrying about infrastructure, caching and scalability. Prisma is an open source version of that same pattern.

                                  To the question of whether you should expose your database API to other internal services or not. This very much depends on the kind of architecture you are choosing. If you are building microservices you typically want to ensure that only the microservice owning the data can access and update it.

                                  Facebook has a quite different approach where TAO enforces access control policies, and all services can query the same data. We'll explore how Prisma can support this pattern in the future.

                                  • adamkl 10 days ago

                                    To further this point a bit, because of GraphQLs introspection capability, it becomes easy to combine and proxy existing GraphQL services without redeclaring the schema every time. If you take a look at what Prisma is doing, it’s creating a GraphQL schema based of an underlying data source which you can then generate bindings off of to include in other applications (think auto-generated client bindings via SOAP WSDL files.

                                    At my company, we are taking a different approach by defining GraphQL APIs that are essentially exposing pure data (similar to Prisma) and then we are merging them and proxying them through multiple layers that augment and alter the schema and data as it passes through.

                                    We can do this because we are leveraging The ability to inspect and alter the abstract syntax trees that power GraphQL under the hood.

                                    • sorenbs 9 days ago

                                      This sounds like a super interesting approach Adamkl! Do you have something written up about this somewhere?

                                      • adamkl 9 days ago

                                        I've had a few discussions about doing a formal write-up of what we are doing, but for now I can only provide a brief overview:

                                        Our data APIs map from existing SOAP/XML services to small GraphQL sub-sections of our greater API.

                                        Then, we merge those small APIs together with Apollo's graphql-tools, similar to what Airbnb is doing[1].

                                        Now we are starting work on our proxy/processing layers using this[2] work-in-progress.

                                        [1]https://medium.com/airbnb-engineering/reconciling-graphql-an...

                                        [2]https://github.com/adamkl/graphql-proxy

                              • skndr 10 days ago

                                > - However the worst thing so far to me has been i have watched as UI developers go from writing simple rest queries, and doing a bit of work on the front-end to writing extremely inefficient and convoluted queries. Even worse is when a third party is doing it and i have no say over what they do with it.

                                To your last point, there are a few ways you can provide feedback on or limit the cost of your queries. I'd recommend checking out Github's article on resource limitation [0] and the section on query cost analysis in an article by the Apollo team [1].

                                [0] https://developer.github.com/v4/guides/resource-limitations/ [1] https://dev-blog.apollodata.com/securing-your-graphql-api-fr...

                                • ioddly 10 days ago

                                  Have you looked at Hasura's postgres offering at all?

                                  I haven't used either yet, but I spoke to one of the founders a while back and auth difficulties was one of the things we talked about. I believe they're open sourcing their data layer soon.

                                  • ruslan_talpa 8 days ago

                                    is it a legacy db? can you give more details as to in what domain you have hundreds of tables? with postgraphile, are you exposing your tables directly or did you create a special "api" schema with only views and functions that is exposed as an api?

                                    as for your migrations problems, a combination of sqitch and apgdiff provides a way to work with sql similar to other languages (migration files are created automatically and managed by sqitch)

                                    • knlam 9 days ago

                                      I am sorry but you are using Graphql the wrong way, it should be stressed that GraphQL never and never could replace your SQL(it is a wrapper around your SQL backend)

                                    • isoos 10 days ago

                                      I was very interested about build a fullstack GraphQL system, but early on, I've got the feeling that if you are using a strongly typed language, which has its proper data binding layers (to the DB or to the UI components), then there are very little benefits of using GraphQL. Could somebody share their thought on that?

                                      I mean, I get that react(-like) UI frameworks or node.js servers are happy using it, as this is their version of creating a "narrow" interface. However most platforms do support powerful type-to-serialization mappings through either reflection or code generation. We can create "narrow" interfaces easily, and these can be used with much less hassle than GraphQL.

                                      Can somebody share their story if/when GraphQL were beneficial with a strongly typed language?

                                      • waterfoul 10 days ago

                                        It's really helpful when you have many desperate systems which all hit the same API in different ways. We've built a more custom solution to hit some existing databases and this style of system will be reducing the need for as much custom c# code on each back end. It's also SUPER useful because it will auto-gen the types for our api calls and we no longer have to hand write them. I do see your point though, for existing apps which alreayd have the infrastructure in place this style of system is not as helpful, it's mostly geared at new development and common apis

                                        • isoos 10 days ago

                                          There are many ways that one can define a custom, narrow interface for a service, and automatically generate client code, server stub, and for many cases even database access codes. GraphQL is one of them, it may be one of the not-too-lame ones, but for most practical purposes, it doesn't seem to be clearly better than the average toolkit.

                                        • adamkl 10 days ago

                                          We've actually gone the opposite direction. We start with our GraphQL schema and then generate TypeScript types off of that schema. This is something that's often done on the client side, but we do it on the server side.

                                          With those, we get type safety on input arguments, and can make sure that our data access layer maps from back-end data sources to our output GraphQL types.

                                      • jaequery 9 days ago

                                        I can see the praise of Graphql especially when coming from frontend developers. I do enjoy working with them at the client side level.

                                        But at the backend level, I find Graphql bit too verbose. There is a lot of code being repeated (or referenced) and it makes your code bloated with having to manage several different places.

                                        For example if you have a customers table, you have to declare the fields you have in the table for the schema, then you declare them all again on the queries/mutations/resolvers. Which are again repeated at the client side. So if you ever alter something in your table, you have to touch around 4-5 files for each change. You then multiply that by the number of tables you have and you get the idea. It is essentially worse if your database schema have quite a bit of nested JSON data.

                                        Sure there are pros and cons to this but atleast with me, so far, the cons seem to outweigh the pros. I miss being able to whip up an API endpoint on the fly.

                                        Graphql backend coding reminds me of the days of SOAP with the WSDL and all, I recall it made me hate coding. I was thrilled to see REST get popularized and get away from SOAP completely. Now it seems we are back in a quasi-SOAP world again with Graphql. I'm sure it's a bit more improved now but once being burned I just don't feel comfortable going back to anything that resembles it.

                                        I generally like simple and quick solutions that addresses problems. But Graphql seems like it's in the other spectrum of it. On the bright side, Graphql is somewhat fun. :)

                                        • ex3ndr 10 days ago

                                          What most of the tutorials are usually missing is versioning and schema hygiene. I am building APIs for last 6(?) years and in graphql there are no clean way to have different versions (intentionally) and after only half year of rapid iteration over ideas in my startup our scheme became a mess. I can spend hours trying to figure out how to fix my scheme now (my bad) and i think that this is much more important than basics - they can be easily learned by reading graphql.org.

                                          • y4mi 10 days ago

                                            i don't have a lot of experience with graphql, but your api is hopefully already running behind a reverse proxy... Just run two instances on /api/v1 and /api/v2.

                                            Or use the parameters to specify a version.. but I think the reverse proxy solution is cleaner

                                            • ex3ndr 10 days ago

                                              Sure, but this is not a very clean way. Reverse proxy is not a problem for sure, but writing Resolvers will be a huge pain with no way to make something hacky that won't blow up the whole server.

                                          • mikece 10 days ago

                                            Is it just me or is "full stack GraphQL" a bit of a misnomer? Both on the server/cloud-side as well as the client side (not just JavaScript but binary mobile and desktop apps too) the approaches and libraries for GraphQL are almost legion. Would be nice if there was a type of card catalog resource for GraphQL so that whether your shop is EmberJS and Django or Angular6 and .NET Core or Kotlin/Android Studio and Spring you could be given a pointer to the relevant tutorials for the approaches/libraries/options for your chosen client and server-side technology. (Yes, I realize this link is sort of that but less complete on the server-side stacks -- where is .NET? -- and lacking native mobile and desktop consideration).

                                            • adamkl 10 days ago

                                              I think one of the reasons why there are so many different approaches and libraries out there is due in part to what GraphQL is. Its both more, and less, than an alternative to a REST API.

                                              Its primary use case right now is to replace a REST API, but at its heart, GraphQL is a specification for a type system, query language and the semantics to resolve one against the other. I can’t speak to other implementations, but graphql-js gives you the tools to parse queries and schemes into abstract syntax trees, and once you have that, there’s a lot you can do. With those tools, people have been creating all sorts of things. Take a look at Apollo’s work on merging schemas together for a good example. [1]

                                              Personally, I’m working on a proxy layer that will sit in front of a GraphQL API and act as a sort of business rule engine. It analyses the incoming queries to figure out which sets of rules need to be run.

                                              These sorts of solutions don’t have anything to do with APIs. Heck, you could create a GraphQL schema to act as a classic data access layer, and call it internally from your own code... Which is what Prisma is doing.

                                              I think this ability to leverage the capabilities of GraphQL to create innovative new solutions muddies the waters for those who are looking to create a simple API.

                                              [1] https://www.apollographql.com/docs/graphql-tools/schema-stit...

                                            • kellysutton 9 days ago

                                              Do we need GraphQL? https://kellysutton.com/2017/01/02/do-we-need-graphql.html

                                              (Disclaimer: From my personal blog)

                                              • acjohnson55 9 days ago

                                                The problems you outline are real, but have straightforward solutions. You can persist queries to the server and then GET them in a really natural way, using query params to provide arguments for your GraphQL query's variables. Then, when it comes to caching, just do it at the resolver level, using something like DataLoader, perhaps with a KV store.

                                                • lolive 8 days ago

                                                  For the Semantic Web, I developped a query repository and a query builder GUI (cf datao.net). And my frontend (search.datao.net) fetches thoses queries and apply them upon resource IDs it receives from a search engine.

                                              • 10 days ago
                                                [deleted]
                                                • analogmemory 10 days ago

                                                  This looks awesome. I've been wanting to get a good understanding of how to use GraphQL.

                                                  • jasonm89 10 days ago

                                                    Looks interesting! Gonna give the react + apollo and graphql-ruby tutorials a go.

                                                    • fizb 10 days ago

                                                      from the tutorial:

                                                        const typeDefs = `
                                                        type Query {
                                                          info: String!
                                                          feed: [Link!]!
                                                        }
                                                      
                                                        type Link {
                                                          id: ID!
                                                          description: String!
                                                          url: String!
                                                        }
                                                        `
                                                      
                                                      Why is this rubbish in backticks accepted? It is especially stunning to see this in "modern" ES6+ code explaining the newest hype. It's not even mentioned that it sucks, it's presented like proper code.
                                                      • tomnipotent 10 days ago

                                                        Because it's a string?

                                                        • danlugo92 9 days ago

                                                          It could be done in a type safe manner as opposed to magic strings.

                                                          • tomnipotent 9 days ago

                                                            No, because it's meant to be a declarative language and not ECMA-based. At least spend five minutes understanding what something is before throwing shade.

                                                            • argestes 9 days ago

                                                              Yeah you can do SQL with Hibernate too. It works but it's a nightmare