Persisted Queries in GraphQL

Riyaz NabiyullaRiyaz Nabiyulla
4 min read

GraphQL is a powerful tool for API development, offering flexibility and efficiency. One advanced feature of GraphQL, known as persisted queries, can enhance both performance and security. We will also dive into how the sha256Hash is generated and its role in the query process.

What are Persisted Queries?

Persisted queries are pre-defined, server-stored GraphQL queries that clients reference using a unique identifier, typically a hash. Instead of sending the full query every time, the client sends this identifier, which the server uses to retrieve and execute the query.

Why Use Persisted Queries?

Reduced Payload Size

Sending only the identifier instead of the entire query significantly reduces the payload size. This can improve network performance, especially in mobile applications with limited bandwidth.

Improved Security

Persisted queries limit the set of queries that can be executed on the server, reducing the risk of malicious queries or injection attacks.

Performance Optimization

Since the server already knows the query structure, it can skip parsing and validation steps, leading to faster execution.

How Persisted Queries Work

1. Writing the Query

Let's start with a basic GraphQL query:

query GetUser($id: ID!) {
  user(id: $id) {
    name
    email
  }
}

2. Normalizing the Query

Normalization ensures consistent formatting. This typically involves removing unnecessary whitespace and line breaks. The query might look like this after normalization:

query GetUser($id: ID!){user(id:$id){name,email}}

3. Generating the sha256Hash

The sha256Hash is a unique identifier generated using a hashing algorithm, such as SHA-256. This hash plays a crucial role in the query process as it is used to reference the stored query.

Steps to Generate the sha256Hash:

  1. Normalize the Query: Format the query string by removing unnecessary whitespace and line breaks.

  2. Hash the Query: Use the SHA-256 algorithm to generate a hash of the normalized query string.

Here’s a Python example:

import hashlib

query_string = 'query GetUser($id: ID!){user(id:$id){name,email}}'
hash_object = hashlib.sha256(query_string.encode('utf-8'))
sha256_hash = hash_object.hexdigest()

print(sha256_hash)

This produces a hash like c0704c1d7d87aa3556462815399f81c707d897ddd2bb39924585759192e8e76f.

4. Storing the Query on the Server

The server stores the query and its corresponding hash. This is usually done during a deployment or setup phase.

5. Client Request

The client sends a request with the hash instead of the full query. Here’s an example using cURL:

curl --location 'https://your-api.com/graphql' \
--header 'content-type: application/json' \
--data '{
  "operationName": "GetUser",
  "variables": {"id": "1"},
  "extensions": {
    "persistedQuery": {
      "version": 1,
      "sha256Hash": "c0704c1d7d87aa3556462815399f81c707d897ddd2bb39924585759192e8e76f"
    }
  }
}'

6. Server Lookup and Execution

Upon receiving the request, the server uses the hash to look up the stored query. It executes the query with the provided variables and returns the result if found.

Key Parameters and Transformations

Query Parameters

  1. operationName: The name of the operation being executed.

  2. variables: Any variables required by the query.

  3. extensions: Additional information, including the persisted query details.

Transformation to Persisted Query

  1. Write the Query: Define the GraphQL query.

  2. Normalize the Query: Standardize the query format.

  3. Generate sha256Hash: Create a unique hash using SHA-256.

  4. Store on Server: Save the query and hash.

  5. Client Request: Send a request with the hash.

  6. Server Lookup: Retrieve and execute the stored query using the hash.

Benefits of Persisted Queries

Network Efficiency

Sending a small hash instead of a potentially large query reduces the amount of data transferred over the network, leading to quicker requests and responses.

Enhanced Security

Restricting the executable queries to a predefined set minimizes the risk of executing unauthorized or harmful queries, thus improving security.

Faster Execution

With the query already parsed and validated during storage, the server can directly execute it, saving time on parsing and validation during each request.

Easier Maintenance

Persisted queries make it easier to manage and version control queries. Any changes to the queries are handled in one place on the server, simplifying maintenance.

Conclusion

Persisted queries in GraphQL provide a powerful way to optimize and secure your API interactions. By reducing payload size, enhancing security, and improving execution speed, they make your application more efficient and robust. Understanding how the sha256Hash is generated and its role in the query process is crucial for implementing persisted queries effectively.

0
Subscribe to my newsletter

Read articles from Riyaz Nabiyulla directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Riyaz Nabiyulla
Riyaz Nabiyulla

Tech enthusiast and full-time worker 🚀 Learning DSA in Java to unlock new coding adventures! ☕ Passionate about solving puzzles and embracing continuous learning. Let's connect and build a brighter tech future together!