If you've followed the API economy over the last couple of years, it's impossible to have missed the growing interest in GraphQL. For API providers it offers an alternative to REST, especially as the number of API clients has increased. Under certain use cases, GraphQL offers several advantages over REST, namely the ability to perform complex queries with a single request.
GraphQL isn't a cure-all however and it does have it's own issues as Bruno Soares pointed out in his article on GetNinjas. He breaks the pain points into three categories: those that are nearly impossible to solve, those that are merely hard to solve, and then those where it would make more sense to use an architectural style other than GraphQL.
Problems that are almost impossible to solve include GraphQL's inability to query in indefinite depth. If you have a tree structure from which you want to return a branch but you don't know it's depth, GraphQL has no way of actually confirming that the data it encounters is not infinitely recursive. Without this knowledge, if you allow cyclic queries, you could be opening an attack vector where infinite execution queries can be run. One way of solving this is to use pagination.
Another nearly impossible problem is that because GraphQL responses match the shape of the query, if you need to respond in a spcific format, it may not be possible to shape the response accordingly. The solution here is to add a transformation layer between the client and GraphQL to make the necessary changes.
One of the hard to solve issues is that caching at the network level can become difficult because of the way GraphQL is used over HTTP ie. a POST method over a single endpoint. This can result in URLs that are hard to cache and unreadable. Soares proposes using Persisted Queries though he concedes that this is a complicated way to solve the problem.
File uploads can be difficult because GraphQL modifies server-side data using mutations, but complex data types such as files cannot be passed using mutations. There are a couple of workarounds; one of which is to create an endpoint in REST to upload the file, return the URL and use the URL within your mutation.
One of the benefits of GraphQL is that you can comine any number of fields in your query, but this flexibility can lead to issues with server performance or you may use n+1 queries where you query the database inefficeintly. Soares points out a number of tools and libraries to help deal with these issues.
Lastly comes the case where you have a service that exposes a very simple API and GraphQL will only add extra complexity. They key is to know when an API is simple and when it reaches a level at which GraphQL starts to make sense. The recommendation here is that if an API returns only a few fields and the clients consume those fields in a consistent manner, then a RESTful API may be the better choice.