This does not explain how the client-side cache is kept up-to-date. Cache invalidation matters. You want instantaneous updates on the client if the data has been updated on the server.
E.g. What if the like count has been updated?
Curious what solutions GraphQL offers for this. If it doesn't solve this itself, then what do GraphQL apps do today to solve this?
Facebook does have an internal solution for push updates, I believe they use long http requests. There were some talk of relay adding support for updates via websockets, anyone have any information?
Details about the backend are often vague or missing in every article that covers GraphQL that I've read so far.
Where are guidelines to implement it?
How do we make our existing business code integrate with it?
How do we make sure a client cannot access data from another client?
Does it work well or at all with relational databases?
Is the backend a second-class citizen in this approach?
If you have two fields in a query, does that mean two resolve functions? If I using a SQL database and the two fields were stored on two columns on the same table, wouldn't that cause 2 SQL queries to be run?
Sangria in Scala has a mechanism called "Deferred" that lets you specify that it should ask you to resolve objects of a certain type all at once at the end, and you would do a single SQL query per object type there.
If the JavaScript implementation doesn't have something like this, perhaps it can be hacked on top.
Yes, it feels like the initial Firebase hype. Security? Answer: jazz hands.
I look forward to a sample that implements fine-grained (multi-role) security on a SQL database. Is there a .NET implementation already in development I can contribute to?
About security, I'd also like to see just one example project where Role based authorization is implemented with GraphQL+Relay+React. Unfortunately, despite being so common requirement these days, I couldn't find any so far.
Edit: I'm interested more in GraphQL official JavaScript implementation, since that's the one most people are going to use.
Too invasive. GraphQL actually needs to be implemented on the server, which is a no go for me. The client should not dictate what the server api should look like. I understand it works for Facebook and it's fine, however this thing is so hyped right now developers are jumping into this and promoting this without actually talking about the drawbacks of this tech. And POST requests everywhere? excuse me but it throws away any "natural" http caching.
To me it is another example of something that may benefit a project that has 500 million daily users , that is useless for 99% of projects out there, yet is advertised as a silver bullet that will make a poorly optimized app magically scale.
I believe graphql can be added on top of your backend, even more - it can layer on top of multiple microservices backends to provide single api endpoint
the only problem is that, right now, there's no good lib that you can put on top of your existing infrastructure (for example, django's orm) that can translate graphql -> your-thing. i've been trying to write something like that, but it's kind of awkward, specially because the whole relay stack is not 100% feature stable.
> I believe graphql can be added on top of your backend, even more - it can layer on top of multiple microservices backends to provide single api endpoint
It is exactly what I'm saying. It's yet another layer on the server, it doesn't solve caching issues, and it will certainly not make your average app faster, especially when http2 support is here.
GraphQL is an ORM for rest apis. I thought rest apis were supposed to be universal, why need another layer on top of it? How many ORMs do developers need ? how much more complex does it have to get? The goal of REST is first and foremost readability and simplicity. The purpose of fat clients are to push complexity on the client. With graphQL simplicity is gone since everything is POST thus no http caching, and the server now gets another layer of complexity instead of being client agnostic.
Again, it might make sense at Facebook scale, but many articles promoting GraphQL are not talking about the fact that, it might not make sense for the majority of applications out there, even worse, it actually might make apps slower because of that extra layer.
I think the point was that GraphQL can slice & dice REST interfaces like an ORM, not that GraphQL is REST. I believe this is a part of the story - GraphQL can sit in front of any datasource, not just REST-based ones.
it all depends. with graphql your backend can become really stupid and just handle saving and retrieving data, making it super easy to deploy, scale, archive, etc.
on the other hand having super dump backend makes it expensive to query data, since we have light speed limit for roundtrip between request and response at best.
what graphql does - it shifts point which does all these multiple requests closer to the storage layer and return you processed results based on query you asked.
if you application already returns rich data structures - graphql is probably do not belong here (right now). if you develop true microservices architecture - graphql sitting on top of it certainly might make sense.
Its closest analogue is the unholy beast that is SOAP + WSDL, except without the insanity of XML. With SOAP/WSDL you declare a schema for your API, which then accepts API calls containing parameters. SOAP/WSDL follows a classical RPC paradigm where you execute functions that take positional arguments.
GraphQL dispenses with that terminology, but is still very much RPCish. A key difference is that "arguments" are keyword-based. Where SOAP/WSDL would have you pass a "complex type" (ie., a struct) with optional fields, in GraphQL everything is built out of structs. Another key difference is that the output follows the structure of the input.
GraphQL remaps REST's paths to nested keys. For example, given the routes:
/books
/books/:id
/books/:id/authors
This becomes:
query {
book(id: ...) {
authors
}
}
Where REST doesn't help you is when you want to be able to filter on a lot of things — either your API becomes an explosion of all permutations of relationships, or you do (as many do) create a "query API" that takes all sorts of criteria as inputs. For example: When you get a books' authors you might want to filter by editors only. Or you want to find all books written by an author that were published in the 1950s. REST also doesn't help the client pick which fields to include, or which relationships to follow. Sure, you can implement it on top of REST, but any such solution becomes ad-hoc and app-specific.
Part of that is, firstly, because REST is a set of rules, not a complete protocol, and secondly, REST wants to deal with resources, not queries. Queries (ie., POST to some collection) are left as an exercise for the reader.
Coincidentally, there is no reason why you can't encode GraphQL queries as GET URLs via paths:
/books/id=1/year=1950..1959/authors/name=~John
This probably violates the tenets of REST, which says that resource URLs should uniquely identify a resource. I forget what REST says, if anything, about "views" into resources.
> To me it is another example of something that may benefit a project that has 500 million daily users , that is useless for 99% of projects out there, yet is advertised as a silver bullet that will make a poorly optimized app magically scale.
Do you have some concrete examples where we've done that? We're trying hard in our communication to be honest about the trade-offs that are made.
I'm a big fan of React but it took me a year after its introduction for me to get it and like it. What particularly did the trick for me was one of Pete Hunt's talks he gave a year after release acknowledging the confusion and explaining the reasoning for React rather than just the technology itself.
I feel like GraphQL can be something great and the pain points they identify with typical APIs are stuff I've felt but GraphQL just feels incomplete to me. I feel they're focusing too much on what GraphQL looks like on the client-side and not enough what it looks like on the server-side. The biggest question I have is what's going to process the GraphQL query on the server to fetch the data from the actual datastore? What does that look like when working with typical datastore such as a SQL-based database? The closest thing I've seen that answered that question was this blog post[0] which doesn't look very appealing if that's what the server-side implementation is going to look like. The blog post's implementation looks like a more complicated version of my own APIs which are usually a series of custom endpoints based on my client's needs. I don't see the big deal right now. Maybe next year...
Pulling data from a datastore is up to you. You can use whatever library you like to pull data in. All you have to do is make your `resolve` methods just return the data.
The GraphQL schema definition is basically an adapter (as in adapter pattern) on top of your datastore(s).
I found this example in the dataloader README useful, as it deals with loading from a SQL-based database, with relationships, which is similar to the first project I'm planning on trying it with:
GraphQL means UI components can stand on their own - they work without custom endpoints. And it's faster. You do need to write an adapter between GraphQL and your datastore, which is probably hard today, and probably easier next year, but you only need to pay that cost once.
> The biggest question I have is what's going to process the GraphQL query on the server
It's really not much different from processing a REST-based API request. In theory, you could parse the request and then just execute the necessary SQL to fill out the result.
However, what Facebook's GraphQL library lets you do is define a schema that specifies how each piece of the result is fetched. It's like a declarative API builder. ("GraphQL" is a huge misnomer; it's neither graph-query-oriented, nor is it a query language — it's a protocol.) GraphQL-the-language doesn't make much sense until you look GraphQL-the-library and understand its design.
For example, let's say the GraphQL query is:
query {
story(id: "1") {
text
}
}
Your schema might be declared like this:
const storyType = new GraphQLObjectType({
name: 'Story',
description: 'A story.',
fields() {
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'The ID.',
},
text: {
type: GraphQLString,
description: 'The text.',
}
}
});
const queryType = new GraphQLObjectType({
name: 'Query',
fields() {
story: {
type: storyType,
args: {
id: {
description: 'ID of the story to fetch',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve(root, {id}) {
return SQLDatabase.findStoryById(id)
}
}
}
});
You declare static fields as well as resolver functions that take arguments and are expected to furnish the query with the actual results. You then "execute" the query, which will cause the resolver's to run as they are triggered by parts of the query. For example, if the storyType contains resolvers, any nested queries will invoke them.
I recommend looking at the tests [2] in the GraphQL JS library, because they show some useful examples. There's already a Ruby [1] library for declaring schemas in the same way.
If you're doing SQL underneath, optimizing a GraphQL query into the fewest possible SQL queries might be tricky. For example, let's say each story has an author; doing an author query per story isn't going to cut it; you're going to want to join the authors table. But the outer queryType doesn't know if the query will be asking for the authors. I don't know if the library provides any way to solve this yet.
We're building a single page app with all the rendering done on the client(clichéd, yeah) and a RESTish Dropwizard API server
We have a page which requires integrating data from 12 different REST APIs. Making 12 HTTP requests takes a lot of time. So the obvious solution is to merge the APIs on the server and make a 'business' API specific to that page.
But we did not want to repeat all the merging logic on the server during launch.
To alleviate the problem, I created a dependency graph/DAG for all the 12 APIs and fired HTTP requests concurrently at each level instead of using 12 promises which increased performance significantly.
All the examples I've seen so far have a "hardcoded" schema expressed in code. Besides code generation, is there some way to express a schema in another format?
Is anyone working on a way to define dynamic schemas? For example, a user defined schema rather than a developer defined schema.
What I'd really like to see is a tool/library/framework to create a graphQL schema, store it in a database along with the data, and efficiently query the whole assembly. I'm thinking of something like Semantic Mediawiki that isn't terribad. :)
43 comments
[ 3.3 ms ] story [ 88.5 ms ] threadCurious what solutions GraphQL offers for this. If it doesn't solve this itself, then what do GraphQL apps do today to solve this?
I'd think something along the lines of Surrogate Keys/Cache Tags would make sense:
- https://www.drupal.org/developing/api/8/cache/tags
- http://info.varnish-software.com/blog/advanced-cache-invalid... (ugh, they broke their site, cached at https://pinboard.in/cached/a31c4630dd2d/)
- https://www.fastly.com/blog/surrogate-keys-part-1
- https://blog.cloudflare.com/introducing-a-powerful-way-to-pu...
Where are guidelines to implement it? How do we make our existing business code integrate with it? How do we make sure a client cannot access data from another client? Does it work well or at all with relational databases?
Is the backend a second-class citizen in this approach?
You basically define the schema, and for each method you want to support you implement pulling the data from your datastore.
Authentication is up to you - stick a bearer header on your requests and implement checks in your server and you have secure backends, etc.
Just implement resolve.
If the JavaScript implementation doesn't have something like this, perhaps it can be hacked on top.
eg: { firstName, lastName } doesn't need to load new rows but { mother { name }, father { name } } does need to load new rows.
DataLoader (https://github.com/facebook/dataloader) is a small utility which makes batching and caching database requests straight forward.
I look forward to a sample that implements fine-grained (multi-role) security on a SQL database. Is there a .NET implementation already in development I can contribute to?
Edit: I'm interested more in GraphQL official JavaScript implementation, since that's the one most people are going to use.
To me it is another example of something that may benefit a project that has 500 million daily users , that is useless for 99% of projects out there, yet is advertised as a silver bullet that will make a poorly optimized app magically scale.
you need to implement resolve method to map properties to your backend(s)
yes, it is not drop in, but using any node.js http request library should do the trick.
also, both can co-exist if you have application which already uses existing rest api layer.
It is exactly what I'm saying. It's yet another layer on the server, it doesn't solve caching issues, and it will certainly not make your average app faster, especially when http2 support is here.
GraphQL is an ORM for rest apis. I thought rest apis were supposed to be universal, why need another layer on top of it? How many ORMs do developers need ? how much more complex does it have to get? The goal of REST is first and foremost readability and simplicity. The purpose of fat clients are to push complexity on the client. With graphQL simplicity is gone since everything is POST thus no http caching, and the server now gets another layer of complexity instead of being client agnostic.
Again, it might make sense at Facebook scale, but many articles promoting GraphQL are not talking about the fact that, it might not make sense for the majority of applications out there, even worse, it actually might make apps slower because of that extra layer.
If accurate, this might be the key take-away from this discussion.
on the other hand having super dump backend makes it expensive to query data, since we have light speed limit for roundtrip between request and response at best.
what graphql does - it shifts point which does all these multiple requests closer to the storage layer and return you processed results based on query you asked.
if you application already returns rich data structures - graphql is probably do not belong here (right now). if you develop true microservices architecture - graphql sitting on top of it certainly might make sense.
as usual - it depends :)
No, GraphQL is a protocol that replaces REST.
Its closest analogue is the unholy beast that is SOAP + WSDL, except without the insanity of XML. With SOAP/WSDL you declare a schema for your API, which then accepts API calls containing parameters. SOAP/WSDL follows a classical RPC paradigm where you execute functions that take positional arguments.
GraphQL dispenses with that terminology, but is still very much RPCish. A key difference is that "arguments" are keyword-based. Where SOAP/WSDL would have you pass a "complex type" (ie., a struct) with optional fields, in GraphQL everything is built out of structs. Another key difference is that the output follows the structure of the input.
GraphQL remaps REST's paths to nested keys. For example, given the routes:
This becomes: Where REST doesn't help you is when you want to be able to filter on a lot of things — either your API becomes an explosion of all permutations of relationships, or you do (as many do) create a "query API" that takes all sorts of criteria as inputs. For example: When you get a books' authors you might want to filter by editors only. Or you want to find all books written by an author that were published in the 1950s. REST also doesn't help the client pick which fields to include, or which relationships to follow. Sure, you can implement it on top of REST, but any such solution becomes ad-hoc and app-specific.Part of that is, firstly, because REST is a set of rules, not a complete protocol, and secondly, REST wants to deal with resources, not queries. Queries (ie., POST to some collection) are left as an exercise for the reader.
Coincidentally, there is no reason why you can't encode GraphQL queries as GET URLs via paths:
This probably violates the tenets of REST, which says that resource URLs should uniquely identify a resource. I forget what REST says, if anything, about "views" into resources.Do you have some concrete examples where we've done that? We're trying hard in our communication to be honest about the trade-offs that are made.
But it always does. rest client needs rest backend. graphql client needs graphql backend.
I feel like GraphQL can be something great and the pain points they identify with typical APIs are stuff I've felt but GraphQL just feels incomplete to me. I feel they're focusing too much on what GraphQL looks like on the client-side and not enough what it looks like on the server-side. The biggest question I have is what's going to process the GraphQL query on the server to fetch the data from the actual datastore? What does that look like when working with typical datastore such as a SQL-based database? The closest thing I've seen that answered that question was this blog post[0] which doesn't look very appealing if that's what the server-side implementation is going to look like. The blog post's implementation looks like a more complicated version of my own APIs which are usually a series of custom endpoints based on my client's needs. I don't see the big deal right now. Maybe next year...
[0] https://medium.com/@clayallsopp/your-first-graphql-server-3c...
https://github.com/sangria-graphql/sangria-akka-http-example
Pulling data from a datastore is up to you. You can use whatever library you like to pull data in. All you have to do is make your `resolve` methods just return the data.
The GraphQL schema definition is basically an adapter (as in adapter pattern) on top of your datastore(s).
https://github.com/facebook/dataloader#using-with-graphql
It's really not much different from processing a REST-based API request. In theory, you could parse the request and then just execute the necessary SQL to fill out the result.
However, what Facebook's GraphQL library lets you do is define a schema that specifies how each piece of the result is fetched. It's like a declarative API builder. ("GraphQL" is a huge misnomer; it's neither graph-query-oriented, nor is it a query language — it's a protocol.) GraphQL-the-language doesn't make much sense until you look GraphQL-the-library and understand its design.
For example, let's say the GraphQL query is:
Your schema might be declared like this: You declare static fields as well as resolver functions that take arguments and are expected to furnish the query with the actual results. You then "execute" the query, which will cause the resolver's to run as they are triggered by parts of the query. For example, if the storyType contains resolvers, any nested queries will invoke them.I recommend looking at the tests [2] in the GraphQL JS library, because they show some useful examples. There's already a Ruby [1] library for declaring schemas in the same way.
If you're doing SQL underneath, optimizing a GraphQL query into the fewest possible SQL queries might be tricky. For example, let's say each story has an author; doing an author query per story isn't going to cut it; you're going to want to join the authors table. But the outer queryType doesn't know if the query will be asking for the authors. I don't know if the library provides any way to solve this yet.
[1] https://github.com/rmosolgo/graphql-ruby
[2] https://github.com/graphql/graphql-js/tree/master/src/__test...
[0] https://blog.jacobwgillespie.com/from-rest-to-graphql-b4e95e...
We have a page which requires integrating data from 12 different REST APIs. Making 12 HTTP requests takes a lot of time. So the obvious solution is to merge the APIs on the server and make a 'business' API specific to that page.
But we did not want to repeat all the merging logic on the server during launch.
To alleviate the problem, I created a dependency graph/DAG for all the 12 APIs and fired HTTP requests concurrently at each level instead of using 12 promises which increased performance significantly.
Does GraphQL support such use-cases?
https://github.com/mugli/learning-graphql
Is anyone working on a way to define dynamic schemas? For example, a user defined schema rather than a developer defined schema.
What I'd really like to see is a tool/library/framework to create a graphQL schema, store it in a database along with the data, and efficiently query the whole assembly. I'm thinking of something like Semantic Mediawiki that isn't terribad. :)