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.

The Great Part

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.

Conventions can make good public APIs

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?

{  
  "errors": [{
    "message": "Rate Limited",
    "code": "RATE_LIMITED" 
  }]
}

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.

Discovering Use Cases

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

Security?

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.

Oh, and Performance

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

Will we See More Public GraphQL APIs?

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.

Enjoyed the post? Subscribe to Production Ready GraphQL!