I recently gave an intro talk on GraphQL after performing a spike for one of our products at JPMorgan. The following’s the script I used. I’ve stripped out some parts for regulatory reasons. For the same reason, I also can’t obtain the Powerpoint presentation file. But the generic bits are still useful for those new to GraphQL.
Today I’m going to be talking about GraphQL, how it’s different from REST, what are some of its benefits and limitations. This is more of an intro talk, I won’t go too much in deep because the content is based on a 1-week spike on Product name API. But I believe it will be useful for those who are new to GraphQL.
What GraphQL is not?
- It’s not a database (like a Graph db).
- It’s not a library or a framework by itself (you can’t install GraphQL).
What is GraphQL?
- Query language for your API - allows you to query deeply nested associations
- Specification for servers to execute the query
Why was it created?
- In 2012, Facebook started the project to overcome data fetching issues in their native mobile platform.
- Built with the goal of being a more flexible and efficient alternative to REST.
Why GraphQL?
- Provides clients the power to ask for exactly what they need and nothing more.
- GraphQL APIs get all the data your app needs in a single request
- Language agnostic - plenty of client and server libraries are available. There are implementations of GraphQL like Apollo, GraphQL Java
Comparing to REST
Let’s take an example of a shopping cart and the data needed to populate the following UI
What kind of data do we need? And how would you build a REST API for this?
- Cart resource - list of products, cart value
- Product resource - title, description, price, product image URL, bunch of other things
- If you’re truly REST, you’ll have hyperlinks to other resources which will make your API discoverable
RESTful queries
1
2
3
GET /carts/<id>
GET /products/<id> // x3
GET /product_images/<id> // x3
- That’s 7 round trips!
Can we make it a single request?
- I can use a query param, expand my associations
/carts/<id>?expand=products
- Problem with this approach: stuck with the entire product resource even though you only need title, desc, price
- Even more clever, specify which fields you want
/carts/<id>?fields=products(name, description, price)
- Problem with this approach: that’s only 1 level deep, what if you had to go a level deeper
The GraphQL query equivalent is as follows
The following is how the schema corresponding to the objects in this UI would look like:
References: GraphQL Schema Design by Giroux
Core concepts
- Scalar Types
- Boolean
- Number
- String
- ID
- Query, Mutation
- Custom Types
- Enums
Demo
- Domain: stripped out
- Entry point: stripped out
- Graph - edges, nodes: stripped out
- Types: stripped out
- Playground
- It’s a tool built by the GraphQL community which allows you to not only execute queries against the API, it also provides a documentation of the schema
- As a developer it’s useful to provide pre-configured queries with placeholders or query variables that you can ask your customers to replace and then just press the play button
- Let’s explore the Rule Type
- Entry point
- Explain non-nullable
- Code: stripped out
- Authn/Authz: stripped out
Gotchas
- InputUnion type is missing: Github Issue Output object type Union is present but Input Union type is still in RFC. So until it’s available, all checks must be performed server-side. E.g., Applies in the case where a user should specify only either type A or type B but not both while performing a mutation query. While it’s possible to verify this while querying due to the presence of Union type it’s not possible to enforce this in mutations.
- Dynamic key value pairs should be avoided so that we get the benefit of static type checking enforced by GraphQL. For e.g., in the case of labels, we can use a Label type which has a
key
andvalue
as keys. And it will look like the following: https://stackoverflow.com/a/46563788 - GraphQL Playground, unlike GraphiQL doesn’t allow queries to be populated with URL query params. The next best alternative is to set default queries via tabs.
- Reference
- Playground is the more recent and strategic IDE solution promoted by Apollo, and generally has more features than GraphiQL (the above is an exception).
- Also, Playground and GraphiQL are joining forces
- They seem to be working on GraphQL Explorer which appears to be waay more comprehensive than Playground and GraphiQL but seems to require an Apollo account.
- Playground in production
- Enabling introspection in production is not considered a best practice for security reasons as it exposes the schema and allows attackers to execute malicious queries. Reference
Limitations
- GraphQL is new (released in 2015). Source: The Case Against GraphQL - Robert Zhu
- Cost of learning and getting buy-ins
- Needs time to mature - JS community is mature, but community support is not yet great for other languages
- Control - in GraphQL, unlike REST, the server no longer has full control so there is a possibility of a rogue client making non-performant queries (can be avoided using persisted queries or depth limiting)
- Centralization
- Naming congestion due to a single large graph/schema
- vs. Federation. Centralization (having one giant schema for the entire GT Portal) against a very large codebase may not be practically possible. In Facebook, the largest GraphQL schema had over 10000 types, which resulted in weird type names like NewsFeedDepth4
- Graphs vs Resources - many features in REST not available in GraphQL
- ORMs are optimized for REST currently which means they can avoid issues like the N+1 issue • Like other proxies, it presents another point of failure as there is an additional another layer
Tooling (for learning)
- I completed the GraphQL: The Big Picture Pluralsight course by Adhithi Ravichandran. You can check out my notes from that course to get an overview.
- Many public playgrounds to get a feel for querying
Final thoughts
- Cool documentary by HoneyPot on YouTube
- Thank you and happy querying!