Both of these solutions made progress towards the end goal of a good user experience, but never got there all the way. That takes us to the defer directive. As you might have guessed, defer is a possible solution to the ongoing problem of higher latency fields while still having a single response. Defer is a directive used by clients to inform GraphQL servers that the requests can be delivered incrementally by specifying parts of a query that were returned later. As of today, this directive is not part of the official GraphQL specification. However, it's been used by a number of companies in production already. It is currently under the working group with a publicly accessible RFC which covers ins and outs of the directive and I'll have a link to the RFC at the end of the presentation. By making defer indicated by the client instead of the server, we can now let the clients inform the server of what fields can be responded to later and which ones cannot. So how does this directive actually work? Is it magic? Well, it's not magic, but it might seem like it after working with it for the first time. We'll be covering this at a high level today for the sake of time, but there are excellent talks and posts covering the more technical aspects of the directive, as well as the RFC from the Working Group. So consider the basic schema for a fictional social media site, which has a query to return a list of users, as well as a user type with a list of friends. In this example, the company running this GraphQL schema notices that the friends field isn't as performant as it probably should be. Now, given the query on the left to fetch the list of users along with their friends, we send the requests and it takes a second for the entire response. This isn't great, and as a client developer, we could render the user data partially before rendering the list of friends for each user.
Both of these solutions made progress towards the end goal of a good user experience, but never got there all the way. That takes us to the defer directive. As you might have guessed, defer is a possible solution to the ongoing problem of higher latency fields while still having a single response.
The first question you might ask yourself is, what is this defer directive thing? And it's a great question. Defer is a directive used by clients to inform GraphQL servers that the requests can be delivered incrementally by specifying parts of a query that were returned later. Or in other words, by deferring the response.
As of today, this directive is not part of the official GraphQL specification. However, it's been used by a number of companies in production already. It is currently under the working group with a publicly accessible RFC which covers ins and outs of the directive and I'll have a link to the RFC at the end of the presentation.
As a quick sidebar, we've all seen directives used in server-side applications. From formatting information, to Apollo Federation notation, and more. But the GraphQL specification also calls out the ability to use them in the query itself. In general, I'm a big proponent of executable directives or client-side directives. They allow for clients to provide additional context to defer use and processing, and not simply notation in the schema about expected behavior as with server-side directives. We've seen client-side directives in the past with things like skip and include as defined in the specification and defer is much the same.
So why do I bring this up? By making defer indicated by the client instead of the server, we can now let the clients inform the server of what fields can be responded to later and which ones cannot. Now the requests are the same. It can be located for portions of a query in one component, but that same query may be returned as one response in another component. That context is hard to convey without defer. So now back to regular scheduled programming.
So how does this directive actually work? Is it magic? Well, it's not magic, but it might seem like it after working with it for the first time. We'll be covering this at a high level today for the sake of time, but there are excellent talks and posts covering the more technical aspects of the directive, as well as the RFC from the Working Group.
So consider the basic schema for a fictional social media site, which has a query to return a list of users, as well as a user type with a list of friends. In this example, the company running this GraphQL schema notices that the friends field isn't as performant as it probably should be. I want to explicitly call out something here, however. The friends field, while returning a list of non-null users, is itself nullable. This is important and is something we'll touch on in a bit as to why that's the case.
Now, given the query on the left to fetch the list of users along with their friends, we send the requests and it takes a second for the entire response. This isn't great, and as a client developer, we could render the user data partially before rendering the list of friends for each user. On a user profile, we probably render their username, contact information, and more.
Comments