Skip to Content
DocsSecurityPersisted OperationsOverview

Persisted Operations

Persisted Operations refer to the concept of optimizing and securing GraphQL requests by replacing the full query string with a unique identifier. This can include the use of Persisted Operations (PO) to achieve the goal of reducing network overhead and improving performance and Automatic Persisted Query (APQ) operations solely for performance improvements.

Stellate GraphQL persisted operations allow you to save and reuse GraphQL operations on the server-side. Instead of sending the entire query/mutation every time, you can send a reference to a previously saved operation.

💡

If you’re already using persisted-operations, you can adopt Stellate. By making us aware of your persisted operations, you can start using Stellate for metrics, caching, and other GraphQL features. If the origin supports persisted operations, you need to set sendHashToOrigin: true in your stellate configuration. Otherwise, sending query strings to the origin server may disrupt functionality as these strings are likely to be rejected.

If you don’t have persisted-operations support on your current origin server, we can also support you. You can generate the persisted-hashes for your client and tell Stellate to not send the hashes to the origin. We’ll send you the query-string instead.

Generally, Persisted Operations work as follows

  • Upload a JSON file: You start Persisted Operations by uploading a JSON file either using the Stellate CLI or API. This file will contain the unique identifier for an operation.
  • Reuse Operation Identifier: In requests, clients can use the unique identifier of the saved operation instead of sending the entire operation again.

Persisted Operations Benefits

Using persisted operations can provide the following benefits for your GraphQL queries:

Cache Busting

When using Persisted Operations with a CDN, you need to handle cache busting. Stellate offers automatic and manual cache purging. Automatic purging analyzes mutations to determine cache invalidation, while manual purging generates a specialized GraphQL endpoint for purging traffic based on your schema.

Reduced Payload

Using Persisted Operations can reduce the payload size of GraphQL requests, especially for repeated operations. The server already knows the details of the operation based on the identifier provided by the client.

Infrastructure Support

Stellate enables you to adopt the infrastructure needed to sync allowed persisted operations. We do this by unfurling persisted operations in our CDN or we start supporting you, if you have already adopted persisted operations.

Observability

When you use Stellate persisted operations, you can also get the benefit of Stellate provided observability insights to track and analyze the performance and effectiveness of your persisted operations.

Types of persisted operations

Stellate supports two different types of persisted operations that serve as different approaches that optimize GraphQL requests by replacing the full query string with a unique identifier. There are two main types: Persisted Operations (PO) and Automatic Persisted Query (APQ) operations.

Persisted Operations (PO)

Persisted Operations involve registering operations on the server side. This allows the Stellate CDN to act as an operation safety bulwark. As such, Stellate Persisted Operations is a security feature as much as a performance one. Each query is assigned a unique identifier, typically a hash of the query string. When a client wants to execute a query, it sends the identifier instead of the full query string. The server then looks up the query in the Persisted Query List (PQL) and executes it. Persisted Operations provides both performance benefits and security, as only registered queries can be executed.

Automatic Persisted Query (APQ)

Automatic Persisted Query operations take a different approach by automatically transforming the query on the client side into a unique identifier, without explicit reliance on the ad hoc generated PQL. APQ eliminates the need for a separate registration step, simplifying the implementation process. Read https://stellate.co/docs/platform/automatic-persisted-queries to find out more about APQ.

Differences between persisted operations types

The differences between persisted operations (PO) and automated persisted query (APQ) operations include the following:

Registration Step

Persisted Operations require a separate registration step where queries are explicitly registered with Stellate. Automated Persisted Query eliminates this step by automatically transforming the query on the client side. However, Automated Persisted Query does this step on the client-side at runtime, and when the server responds by not knowing the query, Automated Persisted Query sends a second request registering the query.

Security

Persisted Operations provide an additional layer of security as only registered queries can be executed, while Automated Persisted Query relies on the client to transform the query, potentially allowing unauthorized queries from other sources.

Query Transformation

Persisted Operations rely on the build step/CI process to perform the transformation from query string to identifier, whereas Automated Persisted Query performs the transformation on the client side.

Before you begin

Before you enable or disable persisted operations, you need to have:

  • A Stellate.co account and login.
  • A working Stellate Service.
  • A GraphQL client setup.
  • A client generated persisted-operations JSON file that contains all the operations used and the generated identifiers. The query needs to add __typename to the selection-sets for Stellate to be aware of the types they are querying. The Relay client, GraphQL Code generator, and the Rover apollo-cli support this feature and have configurations for types. Note that the links are informational and do not represent an endorsement of these tools.

Methods for using Persisted Operations

Stellate gives you multiple methods for enabling, adjusting, and using Persisted operations:

via Stellate CLI

You can enable Persisted Operations by uploading a file through our CLI command. See the following sections for more information.

To upload Persisted Operations in Stellate, you can run the following CLI command:

Persisted Operations CLI command:

stellate persisted-operations push ./po.json

The po.json file is a mapping of hash --> query

via Stellate API

You can use the Stellate Public API to programmatically enable Persisted Operations. The API provides endpoints to manage the configuration settings for APQ and other related features. By making appropriate API calls, you can enable or disable Persisted Operations as needed.

Note: To use the public API, you must create a user token first. Head to your Access Tokens page, click the Create a token button, and name the new token. Make sure also to copy the token to a safe place; you won’t be able to see it again.

To use the Stellate Public API for Persisted Operations:

  1. Navigate to Stellate Docs > Public API > https://graph.stellate.co/ .
  2. Click the Show Documentation Explorer at the top of the Left Navigation Bar.
  3. Find the following APIs or simply click on them.

The Persisted Operation APIs contain the Implements and Fields information for the selected API call.

Example Mutation

You can use our public API to upload persisted operations. The following example shows the use of a mutation that is designed to upload persisted operations with a given service ID and an array of persisted operations.

mutation UploadPersistedOperations(
  $serviceId: ID!
  $persistedOperations: [PersistedOperationsInput!]!
) {
  uploadPersistedOperations(
    serviceId: $serviceId
    persistedOperations: $persistedOperations
  ) {
    id
  }
}

Variables for the mutation example

The following example shows how you can upload Persisted Operations with variables. The example pairs with the prior mutation example. In this example, the variable $limit is a variable of type Int and is used in the pokemons query to limit the number of results returned. You need to set the variable with a specific value when executing the query.

{
	"serviceId": "your-service-id",
	"persistedOperations": [
		{
			"hash": "some-hash",
			"query": "query($limit: Int!) { pokemons(limit: $limit) { id name __typename } }"
		}
	]
}

via Dashboard

You can configure Persisted Operations in the Stellate Dashboard. These settings can be adjusted based on your specific requirements.

To use Persisted Operations in the Stellate Dashboard, login to your Stellate account. Once you login, click the button in the upper left that lists your organization name and perform the following steps:

  1. Navigate to your Stellate Services and click on the Service that you want to work with. ****
  2. For your Service, click on the Security tab, between the Requests and Schema tabs.
  3. In the Persisted Operations view, review all of your operations by
    1. The operation name of the query.
    2. The hash, when you created it.
    3. When we’ve last seen it in our metrics.
  4. Next, click on the Config tab to open the Config Editor.
  5. In the Config Editor, enter the persistedOperations:{ key to see a menu of persisted operations. These are:
    1. apq: This operation is set totrue by default. You can set it to true or false to enable or disable automatic persisted queries (APQ). The APQ operation allows you to toggle our existing automatic persisted queries option off or on.
    2. rejectInvalidHashes: This operation is set to false by default. If the operation is set to true, it rejects anything that is not a query hash, such as a stringified query user. As such it allows any normal query or query hash to be sent. Keeping the default as false can incur security risks. Setting this operation to true provides an extra layer of security for your queries.
    3. SendHashToOrigin: This operation is set to false by default. Set this operation to true, when the origin knows about persisted operations, to have Stellate send the hash to the origin server from our CDN. In this case, we translate the persisted operation inside the CDN, send the query string onto the origin server, and then your origin needs to unfurl the hash to the query string. Set this operation to false, when the origin doesn’t know about the persisted operations. When set to fale, we send the query-string as you will already have an unfurled hash because Stellate did it in the CDN.
Last updated on