Why We Don’t See Many Public GraphQL APIs

GraphQL is both a great and not-so-great choice for a public API

👋 I have just released an entire book on building GraphQL servers that goes into great detail on building GraphQL servers at scale: https://book.productionreadygraphql.com

Check it out if enjoy this kind of content!

I was at the API Specifications Conference last week to give a talk and a panel and had the chance to attend a workshop given by Tim Burks from Google. Tim talked about powering GraphQL and REST APIs with gRPC. It was truly an interesting talk. One thing he said during the workshop is that there we can generally categorize APIs out there in three broad groups:

  • Private APIs (Internal to a company)
  • Partner APIs (Shared with a limited amount of partners)
  • Public APIs (Fully public APIs accessible by mostly anyone)

One thing he noticed is that most GraphQL APIs seem to be found in the private and partner categories. And it’s true! Even Facebook themselves don’t have a public GraphQL API at the moment, and a lot more people are using it internally. As far as I know, Shopify and GitHub are at the moment probably the largest public GraphQL APIs out there. Why are public GraphQL APIs so rare? I think there’s a few reasons.

A public API (if successful) means a ton of possible clients. Handling so many various use cases can become quite hard to handle for API providers, and failure to handle these use cases becomes cumbersome for clients, dealing with generic and one-size-fits-all APIs.

The GraphQL specification, not only its query language turns out to be quite good at handling such situations. The type system, resolver pattern and query language all together allow providers to define as many capabilities and variations as they want without extra cost on existing clients (Think for example typical enormous webhook or HTTP endpoint payloads). GraphQL also offers a good and most of the time simple mental model and architecture for API engineers. I won’t bug you more with this point since I’ve talked about it a lot.

It turns out HTTP is quite useful 🙊. A bit like gRPC or other API styles that have their own specific protocols, a lot of things have to be reinvented with a GraphQL API. Errors, caching, rate limiting, timeouts, and so many other things are handled in many different ways by GraphQL API providers at the moment. Part of it is because best practices are still emerging and another part of it is that because the GraphQL specification doesn’t say anything about it, which is wise in many ways. Currently a GraphQL client must learn how a certain provider handles all these things. Is the GraphQL server using errors in data, or using GraphQL errors? Is the GraphQL API returning 429 or has a custom error encoded when a client gets rate limited? What about cache hints? Every time a client interacts with a new GraphQL API, they have to find either through exploration or documentation how all these things must be handled. Compare this to an HTTP API, where you can most of the time expect the right behavior when you throw an HTTP client at it.

Of course a lot of this is a challenge to HTTP APIs too, which is why you’ll always hear the advice of using as many HTTP concepts as possible before implementing your own logic. Should public GraphQL APIs served over HTTP return a 429 TOO MANY REQUESTS or more something like this?

With 429, most of HTTP libraries will handle these requests perfectly. With the other approach, we require clients to learn a whole new “protocol” for our API, try and learn about every error possible and how it’s expressed in this particular API. This also explains why generated clients are so popular with things like gRPC, since companies can generate their own concepts into clients instead of letting users with generic clients try to handle these scenarios.

Going forward there are things that might help:

  • GraphQL conventions: The best practices have maybe not been figured out so much yet. Errors in particular are still not a solved problem.
  • Using a bit more HTTP in your GraphQL API. It’s still hard because GraphQL query doesn’t represent necessarily one resource, meaning things like 404 and 422 for example can’t be used very easily. Still, I can see using 401 and 429for example.
  • Generated Clients, maybe some way for companies to generate some client plugins for major clients even? Would need to consider many clients which is annoying… You can see how the lack of conventions makes things trickier.

One advantage of “One-Size-Fits-All” style APIs is that the client doesn’t need to think too hard to get started. Want to get a user? Simply GET this endpoint. With GraphQL, clients are in charge of defining their use cases, which can be both great and terrifying. I’ve talked about this a little in that post on the GraphQL burger analogy.

There are ways to make this better, which is by making sure documentation for a GraphQL API doesn’t stop after generating a big reference from the schema. Of course this is the case for any API, but GraphQL inherently makes discovering use cases a bit harder for clients, which means we have to be extra careful about it. GraphiQL is an example of a tool that greatly helps, but most GraphQL documentation out there could do a better job at focusing on what the API enables clients to build rather than just an enormous list of fields a client can query.

Shopify’s GraphiQL Explorer

People will tell you GraphQL is not used publicly because it is inherently insecure, by letting anyone query for everything! This is false since an API provider should specifically curate a schema, assuming they’re not just generating a schema from their database schema, which I don’t recommend either way.

There are things that are a bit harder in terms of securing your API.

  • A GraphQL rate limiter needs to understand the content of requests a lot more compared to a typical HTTP API, this usually leads to a complexity or time based approach to rate limits.
  • Authorization in GraphQL is not really harder to implement than in another API. However it can be hard to make sure there are no loop holes at runtime, for example, accessing a type through a field you did not think of.

Both of these things are solvable and have generally good solutions however. In fact I think the security argument we hear so much is not as much of a good one as the others we covered.

I’ve written a post entirely on this subject! Read more about this here.

As you can see, GraphQL is great for some reasons and not so great for other reasons when it comes to building a public API. We have to once again consider the tradeoffs. However, if GraphQL keeps being loved like it is right now by client developers, we might see a GraphQL API becoming more of a concern for companies exposing public APIs. As we saw, it also can benefit the provider a lot and help handle so many different use cases without falling in the One-Size-Fits-All mentality (Oh, by the way, it is definitely possible to fall in that trap with a GraphQL API too). Internal GraphQL APIs usually makes the life of the API team a bit easier, since they can set standards within the company. Public API GraphQL providers will need to be careful about standards. In the future, it would be interesting to see if several companies with large public GraphQL APIs can agree on a set of best practices and conventions going forward.

#GraphQL Enthusiast, Speaker, Platform Interface Engineer @ GitHub 📖 Book is now available https://book.productionreadygraphql.com/