docs: improve some basic docs on caching

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8887
Co-authored-by: Rob Dominguez <24390149+robertjdominguez@users.noreply.github.com>
GitOrigin-RevId: 0597ca635eaf370053f0158925c6a531cc643311
This commit is contained in:
Anon Ray 2023-05-22 14:05:52 +05:30 committed by hasura-bot
parent 30fbdf2e83
commit 37384ec60d
3 changed files with 198 additions and 33 deletions

View File

@ -5,7 +5,7 @@ keywords:
- queries
- query
- config
sidebar_position: 3
sidebar_position: 4
---
import ProductBadge from '@site/src/components/ProductBadge';
@ -23,6 +23,9 @@ Schemas.
Cached responses are stored for a period of time in a LRU (least-recently used) cache, and removed from the cache as per
a user-specified TTL (time-to-live) which defaults to 60 seconds.
For self-hosted Enterprise Edition, refer to the [enable caching](/enterprise/caching.mdx) documentation configure
various parameters.
## Getting started
In order to cache a query response, or to return an existing response from the cache (if one exists), simply add the
@ -40,14 +43,6 @@ query MyCachedQuery @cached {
If the response was cached successfully, the HTTP response will include a `Cache-Control` header, whose value
(`max-age={SECONDS}`) indicates the maximum number of seconds for the returned response to remain in the cache.
A query's response can be cached only if the following conditions hold:
- For queries using `Actions` or `Remote Schemas`, the query does **not** make use of `forward_client_headers` (see
[RemoteSchemaDef](/api-reference/syntax-defs.mdx#remoteschemadef) and
[ActionDefinition](/api-reference/syntax-defs.mdx#actiondefinition)).
- The response JSON is **under** 100KB in size
For self-hosted Enterprise Edition, refer to the [enable caching](/enterprise/caching.mdx) documentation.
## Controlling cache lifetime
@ -89,29 +84,6 @@ different query and will generate a new cache key.
:::
## Rate Limiting
Cache writes are rate limited, with a rate depending on your plan. The rate limit is based on the total number of bytes
written to the cache in a sliding window. If you exceed the rate limit, the HTTP response will indicate this with a
warning header:
```plaintext
Warning: 199 - cache-store-capacity-exceeded
```
:::info Sliding window policies
A sliding window policy maintains a queue of a specified size, into which entities flow. When the queue is full and a
new entity arrives, the oldest entity in the queue is removed from the window (FIFO).
:::
## Session variables
A session variable will only influence the cache key for a query if it is referenced by the execution plan. In practice,
this means that session variables are only factored into cache keys if they are referenced in the permissions for a
query. See the [API permissions](/api-reference/metadata-api/permission.mdx) documentation for more information.
## Response headers
When you enable caching for a query, the following headers should be returned in the HTTP response:

View File

@ -0,0 +1,193 @@
---
description: How caching works
title: How it works
keywords:
- caching
- queries
- query
- how-to
sidebar_position: 3
---
## What is cached exactly?
Hasura Caching is a type of response caching that helps you cache results of a given query. Hasura will cache the
response of a given "unique" query, and only if the same query is made again (i.e., has the same cache key) will it hit
the cache. We explain how the cache key is computed in the [next section](#how-is-the-cache-key-computed).
This means that there is no sharing of the cache if:
- the session variables differ, even if the GraphQL query, variables, operation name everything is the same
- the GraphQL variables differ, even if the GraphQL query is the same
- the operation name is different, even if the GraphQL query is the same
- the GraphQL query differs only in one or a few fields
## How is the cache key computed?
If the `@cached` directive is used in a GraphQL operation, Hasura computes a cache key. This is then used to look up and
store values in the cache.
The cache key is a hash of:
- the GraphQL query
- the GraphQL operation name
- the GraphQL variables of the query
- the [role and session variables](/auth/authorization/roles-variables.mdx) used in permissions of the query
- request headers in case of [Remote Schemas](/remote-schemas/overview.mdx) or [Actions](/actions/overview.mdx) when
`forward_client_headers` is `true`
If the computed cache key is found in the cache, then there is a cache hit.
:::info TTL matters
Note that the cache hit also depends on the TTL and not just cache key. See [below](#cache-invalidation) to know more
about cache TTL.
:::
### GraphQL query
This includes the entire GraphQL query text. Any difference in the GraphQL query text is considered a different query.
**Only whitespace is ignored.**
For example, all the following queries are considered **different**:
```graphql
query MyCachedQuery @cached {
users {
id
name
}
}
```
```graphql
query MyCachedQuery @cached {
users {
name
id
}
}
```
```graphql
query MyCachedQuery @cached {
users {
id
name
created_at
}
}
```
If the order of objects inside an input argument are changed, even then it is considered a **different** query:
```graphql
query MyCachedQuery @cached {
profile(where: { _and: [{ id: { _gt: 1 } }, { name: { _ilike: "%x%" } }] }) {
id
name
}
}
```
```graphql
query MyCachedQuery @cached {
profile(where: { _and: [{ name: { _ilike: "%x%" } }, { id: { _gt: 1 } }] }) {
id
name
}
}
```
Only whitespace is ignored, so the following queries are considered the **same**:
```graphql
query MyCachedQuery @cached {
users {
name
id
}
}
```
```graphql
query MyCachedQuery @cached {
users { name id }
}
```
### Operation name
In the following example, the operation name is `MyCachedQuery`
```graphql
query MyCachedQuery @cached {
users {
id
name
}
}
```
If we use the same name, but change the query, then it is considered a **different** query:
```graphql
query MyCachedQuery @cached {
users {
id
}
}
```
### GraphQL variables
The following example shows variables declared and used called `minDate` and `maxDate`. Usually, when executing the
operation, one would pass the actual value of these variables.
If these variable **values** differs across queries, then they are deemed **different**:
```graphql
query getNewlyJoinedUsers($minDate: timestamptz!, $maxDate: timestamptz!) @cached {
users(where: { _and: [{ created_at: { _gt: $minDate } }, { created_at: { _lt: $maxDate } }] }) {
id
name
}
}
```
### Role and session variables
Hasura resolves [session variables](/auth/authorization/roles-variables.mdx) via the
[authentication](/auth/authentication/index.mdx) process. The role and session variables are used to compute the cache
key.
A session variable will only influence the cache key for a query if it is referenced by the execution plan. In practice,
this means that session variables are only factored into cache keys if they are referenced in the permissions for a
query.
For example, if a JWT resolves to say `x-hasura-user-id` and `x-hasura-org-id` session variables, but the query only
uses the `x-hasura-user-id` in the permissions, then only the role and `x-hasura-user-id` would be used to compute the
cache key.
### Request headers
Request headers (ignoring `x-request-id` header) are added to the cache key computation, when executing Remote Schema
or Action queries, if they have `forward_client_headers` set to `true`.
## Cache Invalidation
Cache invalidation in Hasura is based on TTLs. Hasura doesn't support any other "automatic" way to invalidate cache
(like on specific mutations). However, there are
[API endpoints](/docs/caching/caching-config.mdx#clearing-items-from-the-cache) to clear the cache manually.
The default TTL is 60 seconds. This can be increased via the
[TTL argument](/caching/caching-config.mdx/#controlling-cache-lifetime) in the cached directive.
## Rate Limiting
Cache writes are rate limited, with a rate depending on your plan. The rate limit is based on a leaky bucket algorithm.
If you exceed the rate limit, the HTTP response will indicate this with a warning header:
```http
Warning: 199 - cache-store-capacity-exceeded
```