I've used GraphQL on several projects now, with small teams (2-5 devs) where we control the front and back end, and for that case, it's actually been really good. It provides a solid contract that is easy to get wrong with a REST API. (Will the server send IDs as ints or strings? Will it accept either? Which params are optional? What shape does the data come back in, an array of results, or an objects with results nested somewhere? etc.) I've even setup CI to fail if it finds queries on the front-end that don't match the schema. And of course it's easy to request exactly the data you want on the front -end.
A big downside is that the tooling is immature, and all subject to big changes. And I haven't written a server meant for public consumption, but that does add new layers that you can kind of ignore when you trust the client.
If you own the backend and the frontend, I don't see how graphql helps you. You can just implement the APIs that you need to solve your business problems. Now all you're left with are the downsides. I'll pass.
One of the problems backend systems sometimes have is presenting similar data in slightly different ways for use in many different places. One of the solutions to this is GraphQL, which lets you break your data loading into reusable pieces (resolvers) and define endpoints based on those reusable pieces (queries).
You could "just" do this yourself, of course. GraphQL is nice because it gives you a sensible starting point and a lot of free tooling. You get Graphiql to help you quickly write new queries, you get well-defined schemas between server and client, you get linters for queries, you get GraphQL itself to glue your resolvers together and interpret your queries.
If your system has a grand total of 20 API endpoints and they're nearly all unique, you don't need GraphQL.
I listed some ways that it helps. You get a strict, well-defined, easily-documented API. Yeah, you can do all that with REST, but I like having a defined structure for it.
On a large team I’ll often be debugging someone else’s code anyways, and the framework code is usually better than hacked together product code (and comes with a public bug tracker).
On the team I lead, we keep our domain logic pure, encapsulated, and layered. This means that if I have to debug a fellow teammates code, I can be confident that it is only business logic related code and not more technical, library dependent code.
When our code has to interact with other systems, the other systems' responses have to pass through an anti corruption layer and be translated into something we care about. All of this is surrounded with try catch and we quite obsessively check and validate everything coming in and out.
We do all of this because if/when something breaks in some library or framework that we didnt write, it doesnt bleed through to our POJOs. And, if we ever need to switch to the new flavor of the week library which happens quite often, we don't have to rewrite everything, just the adapter classes.
> Will the server send IDs as ints or strings? Will it accept either? Which params are optional? What shape does the data come back in, an array of results, or an objects with results nested somewhere? etc.
Hum... It seems you are missing a data definition language. GraphQL isn't a very good solution to that.
I don't understand how if you're on a team in which you control both the front end and back end, you wouldn't understand these factors - "Will the server send IDs as ints or strings? Will it accept either? Which params are optional? What shape does the data come back in, an array of results, or an objects with results nested somewhere? etc"
Surely you would know all the answers to these questions because your team control the entire stack.
If it was the case that the FE and BE teams were separate, then these would be reasonable considerations, but I just don't see it in a team dealing with full control.
Designing a solid contract can be useful even when you’re one person, for the same reason that decoupling classes or concerns is useful. I don’t need to consult another person or read the code to understand what it’s expecting (especially true in contexts where documentation may not have been written yet).
A big downside is that the tooling is immature, and all subject to big changes. And I haven't written a server meant for public consumption, but that does add new layers that you can kind of ignore when you trust the client.