Live Queries

Live Queries

GraphQL Live Query implementation from Laurin Quast (opens in a new tab) can be used in GraphQL Mesh with a few additions in the configuration.

yarn add @graphql-mesh/plugin-live-query

Basic Usage

You have a Query root field that returns all Todo entities from your data source like below.

query getTodos {
  todos {

And you want to update this operation result automatically without manual refresh when Mutation.addTodo is called.

You only need to add the following to your existing configuration.

additionalTypeDefs: |
  directive @live on QUERY
  - liveQuery:
        - field: Mutation.addTodo
            - Query.todos

Then you can send a live query with @live directive.

query getTodos @live {
  todos {

This will start a real-time connection between the server and your client. The response of todos will get updated whenever addTodo is called.

ID Based Invalidation

Let's say you have the following query that returns a specific Todo entity based on id field;

query getTodo($id: ID!) {
  todo(id: $id) {

If you update this entity with editTodo mutation field on your backend, then you want to invalidate this entity specifically instead of validating all todo queries;

  - field: Mutation.editTodo
      - Todo:{}

In a case where the field resolver resolves null but might resolve to an object type later, e.g., because the visibility got update the field that uses a specific id argument can be invalidated in the following way:

  - field: Mutation.editTodo
      - Query.todo(id:"{}")

Programmatic Usage

liveQueryStore is available in GraphQL Context, so you can access it in resolvers composition functions that wrap existing resolvers or additional resolvers;

See Resolvers Composition

  - resolversComposition:
      - resolver: Mutation.editTodo
        composer: invalidate-todo#invalidateTodo

And in this code file;

module.exports = {
  invalidateTodo: next => async (root, args, context, info) => {
    const result = await next(root, args, context, info)
    return result

Config API Reference

  • ttl (type: Float) - Maximum age in ms. Defaults to Infinity. Set it to 0 for disabling the global TTL.
  • ttlPerCoordinate (type: Array of Object) - Overwrite the ttl for query operations whose selection contains a specific schema coordinate (e.g. Query.users). Useful if the selection of a specific field should reduce the TTL of the query operation.:
    • coordinate (type: String, required)
    • ttl (type: Float, required)
  • ignoredTypes (type: Array of String) - Skip caching of following the types.
  • idFields (type: Array of String) - List of fields that are used to identify the entity.
  • invalidateViaMutation (type: Boolean) - Whether the mutation execution result should be used for invalidating resources. Defaults to true
  • includeExtensionMetadata (type: Boolean) - Include extension values that provide useful information, such as whether the cache was hit or which resources a mutation invalidated.
  • sessionId (type: String) - Allows to cache responses based on the resolved session id. Return a unique value for each session. Creates a global session by default. Example;
sessionId: "{context.headers.userId}"
  • if (type: String) - Specify whether the cache should be used based on the context.
if: "context.headers.userId != null"
  • cacheKey (type: String) - Customize the behavior how the response cache key is computed from the documentString, variableValues, contextValue and sessionId. If the given string is interpolated as empty, default behavior is used. Example;
# Cache by specific value
cacheKey: "{variableValues.userId}"
# Cache by documentString
cacheKey: "{documentString}"
# Cache by operationName
cacheKey: "{operationName}"
# Cache by some header value
cacheKey: "{contextValue.headers.authorization}"
# Or combine two of each
cacheKey: "{contextValue.headers.authorization}-{operationName}"
  • shouldCacheResult (type: String) - Checks if the result should be cached.
shouldCacheResult: "result.errors.length > 0"

CodeSandBox Example


You can learn more about GraphQL Live Query (opens in a new tab) in its documentation. You can check out our example that uses live queries