Support and Documentation

Persisted queries

How to configure persisted queries on your endpoint and the protocol for using them.

Introduction to GraphQL persisted queries

GraphQL queries are an effective method of retrieving data, but the repeated transmission of complex queries hampers network performance due to their length. To remedy this, persisted queries allow client applications to send a hash of a query to Brightspot in place of the full query text. This reduced payload size allows for quicker network transmission between the client and server, while still retrieving the same data. Additionally, this reduced size enables GraphQL queries to be sent via HTTP GET. This allows CDNs to cache the result, further improving performance.

The Persisted Query Protocol

The persisted query protocol, as described by Apollo, defines the interactions between client and server when passing query hashes. Simply put, the GraphQL client makes a request containing the hash of its desired query to a Brightspot GraphQL endpoint. If the endpoint recognizes the hash, it will execute the desired query and send the result back to the client in the response.

How does the Persisted Query Protocol work?

Consider the following query to retrieve the articleBody data of an Article at a given path via a Content Delivery API endpoint:

query ArticleQuery($path: String) {
  ArticlePage(path: $path) {
    headline
  }
}

with the variables:

{
  "path": "/article-path"
}

The steps for executing this request via the Persisted Query Protocol are as follows:

  1. The client sends a hash of the query to execute, plus any variables necessary to complete the request. This can be sent via URL parameters in an HTTP GET request, or in the body of an HTTP POST request.

    GET URL Path:

    /graphql/delivery/article?variables=%7B%22path%22%3A%22%2Farticle-path%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22sha256Hash%22%3A%22c205cf782b5c43c3fc67b5233445b78fbea47b99a0302cf31bda2a8e2162e1e6%22%7D%7D

    Alternative POST Body:

    {
      "variables": {
        "path": "/article-path"
      },
      "extensions": {
        "persistedQuery": {
          "sha256Hash": "c205cf782b5c43c3fc67b5233445b78fbea47b99a0302cf31bda2a8e2162e1e6"
        }
      }
    }
  2. If Brightspot recognizes this hash (either from seeing it in a previous request for Automatic Persisted Queries, or by fetching it from a designated Static Query Mapping), it will execute the associated query and return the results. However, if it does not recognize the hash, an error will be returned instead:

    {
      "errors": [
        {
          "message": "PersistedQueryNotFound"
        }
      ]
    }

    The client's expected response at this point will be dependent on the endpoint's persisted query configuration.

    • If configured with Static Query Mapping, receiving this error means that the query associated with this hash is not authorized to execute against this endpoint. As such, there is no further communication expected between client and server. Attempting to pass the unsupported query/hash combination (in the format of the APQ example below) in a request will result in a PersistedQueryNotSupported error being returned by the endpoint.

    • If configured with Automatic Persisted Queries, then the following steps will take place:

  3. The client sends an HTTP POST request with the same hashed value along with its corresponding query.

    POST Body:

    {
      "query" : "query ArticleQuery($path: String) {\n  ArticlePage(path: $path) {\n    headline\n  }\n}",
      "variables" : {
        "path" : "/article-path"
      },
      "extensions" : {
        "persistedQuery" : {
          "sha256Hash" : "c205cf782b5c43c3fc67b5233445b78fbea47b99a0302cf31bda2a8e2162e1e6"
        }
      }
    }
  4. Brightspot validates the hash. If the sha256hash parameter matches the calculated hash of the passed query, Brightspot stores the query, processes the request, and returns the result.

    {
      "data": {
        "Article": {
          "headline": "Hello World"
        }
      }
    }
    

    If the hash is successfully validated, any future requests to execute this query may omit the query string in favor of its hash, as defined in Step 1.

Configuring Brightspot with persisted queries

To enable persisted queries, navigate to your desired endpoint and locate the Persisted Query Protocol field. Brightspot GraphQL endpoints support two methods of Persisted Queries: Static Query Mapping and Automatic Persisted Queries. The differences between the two are as follows:

Static query mapping

If you want to configure your Brightspot endpoint to only accept a specific set of GraphQL queries, then enabling Static Query Mapping as your endpoint's Persisted Query Protocol is appropriate. You will be able to upload a JSON containing a map of each query key and its corresponding query that the server will run. If a requested key is not recognized, the server will respond with an error and no query will execute.

Automatic persisted queries

On the other hand, if you want your GraphQL endpoint to accept and persist more than a predefined set of queries, the Automatic Persisted Queries (APQ) protocol will allow you to do so. For APQ, the client still sends a query hash to Brightspot when making a request. However, if Brightspot doesn't recognize the hash, it will instruct the client to resend the full query. Upon the client sending the query and its associated hash, Brightspot will save that mapping so all future requests for that query only need to send the hash.

Maintaining APQ mapping parity with Brightspot

Brightspot's GraphQL Explorer tool allows developers to see the expected parameters when performing requests via the Persisted Query Protocol.

After inserting a query into Brightspot's GraphQL Explorer, clicking the gear icon in the top right and selecting Persisted Query Extension will display the GET URL path and POST Body for the requests defined in steps 1 and 3 above. Clicking on the "Advanced" tab will display an additional minified POST body to further reduce the size of requests made by your application. Use this tool to verify that your application's request parameters match those that Brightspot expects to receive for the specified query.

Configuring client applications with persisted queries

The tools linked in the examples below are for use with Apollo applications. While similar tools may be available for other GraphQL clients, Apollo has the most directly applicable integrations with Brightspot's offerings.

Static query mapping

For Static Query Mapping, the PersistGraphQL library allows you to extract all the GraphQL queries used within your application to a JSON file that can be uploaded to Brightspot. By default, this tool makes the key to each query an auto-incrementing integer as opposed to a hash. This will still work with Brightspot, but if you prefer to have an SHA-256 hash associated with each query instead, the PersistGraphQL Signature Sync script will allow you to do so.

Automatic persisted queries

For APQ, the Apollo Link Persisted Queries library provides an extension for an HttpLink (or a custom Apollo Link) to allow for the APQ protocol to take place.