You cannot cache GraphQL.

You've probably heard this multiple times.

Or maybe you're already a bit more educated on the topic and know possible solutions. In that case you would also know that it's definitely possible but takes some work to implement it.

WunderGraph takes care of all this. You can configure caching on the granularity of each individual Query. Caching is possible for public unauthenticated as well as authenticated traffic.

Let's tame the beast!

The basics#

When you first learned about GraphQL one of the first concepts you had to understand is that GraphQL sends Queries via POST requests. Because of this it's not possible to cache these requests. Caching is only possible on GET requests.

The last paragraph is not really accurate. To be more precise, it's not possible for Browsers and intermediate caches like CDNs to cache POST requests.

Persisted Queries#

Some of you might have already heard of persisted Queries.

To get everyone on the same page:

Persisted Queries are a very simple concept. You take a Query, store it on a server and give it a reference. Now you create a GET endpoint that accepts variables as Query string. The Query is now persisted and can be cached easily by HTTP transports.

Here's an example:

query AllOpenTasks {
tasks(done: false) {

If you persist this AllOpenTasks Query your endpoint might look like this:{"done":"false"}

Considerations if you want to roll your own#

  • You have to write and maintain the code
  • You need to deploy and operate another service
  • Will you redeploy the service if the persisted Queries change? Keep in mind that you cannot always upgrade all clients at once
  • You need to figure out the exact headers to set
  • Do you want to support caching for private (authenticated) APIs too? In that case you also have to validate the user's identity
  • Do you want the Cache server to also keep responses in a cache? If so, will you deploy the service multiple times for high availability and performance reasons? If so, you also have to find a solution for a shared memory.

Let WunderGraph take care of it#

Solving all the above problems might not be your core business. With WunderGraph, all Queries are persisted by default. In order to enable Caching for the above example all you have to do is make one small change:

query AllOpenTasks @cache(maxAge: 120) {
tasks(done: false) {

That's it.

@cache(maxAge: 120)

Add the @cache Directive to the appropriate Queries and your WunderNode will take care of everything.