mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 17:02:49 +03:00
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:
parent
30fbdf2e83
commit
37384ec60d
@ -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:
|
||||
|
193
docs/docs/caching/how-it-works.mdx
Normal file
193
docs/docs/caching/how-it-works.mdx
Normal 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
|
||||
```
|
Loading…
Reference in New Issue
Block a user