I’ve worked on projects which had page/task specific endpoints, projects that were strict about keeping endpoints entity specific (traditional REST), and projects that used GraphQL.
I tend to use GraphQL as a default for anything moderately complex or likely to become complex because of the development flow it enables. But this flow also requires apollo; GraphQL is most appealing when you have a good frontend client like apollo.
Here’s the flow: I’ll get a spec for a feature and figure out what data it will need. Specifically, I’ll figure out what data each component in my frontend will need (I often use React). Then I’ll write a naive graphql query in order for each component to fetch the data it needs.
That might sound like a lot of querying and something you could just as easily implement with REST, which would seemingly defeat the purpose of using GraphQL. But apollo enables two things that offsets this, which it can do because of the way in which you can ask for multiple pieces of data at once and the type information GraphQL sends back. If a bunch of queries are made in rapid succession, you can configure apollo to combine those queries into a single network request. It will also cache entities by id and type name and parameters. This means that all of the little queries you write will typically pull from the cache rather than the server, and will be updated automatically if another query or mutation elsewhere in the app alters that entity.
Writing small, entity based queries is typically much faster to implement than creating a new page specific endpoint for every new page/task, as you can reuse and combine queries/types that you’ve already defined. And because of the optimizations apollo makes when deciding whether to query, you often don’t get a performance penalty from it.
At this stage, I’ll evaluate whether or not the performance is acceptable. Normally it is, but sometimes it’s not. When it’s not, I’ll move those little queries that were happening in the components out, and have the component get the data from higher up in the component hierarchy. The component logic stays the same, so the move is cheap in terms of dev time.
I‘ll then write more performant, page/task specific queries (top level graphql query types) that fetch a whole bunch of stuff at once and do so efficiently. If a frontend dev could write a task specific node endpoint, they could write a graphql resolver for a task specific top level query the same way.