diff --git a/packages/plugins/response-cache/README.md b/packages/plugins/response-cache/README.md
new file mode 100644
index 0000000000..02da9b6e91
--- /dev/null
+++ b/packages/plugins/response-cache/README.md
@@ -0,0 +1,3 @@
+# @graphql-yoga/plugin-response-cache
+
+For the documentation check `http://graphql-yoga.com/docs/response-cache`
diff --git a/website/routes.ts b/website/routes.ts
index 55f5551004..854c6420b3 100644
--- a/website/routes.ts
+++ b/website/routes.ts
@@ -103,6 +103,7 @@ export function getDocsV3Routes(): IRoutes {
['testing', 'Testing'],
['persisted-operations', 'Persisted Operations'],
['automatic-persisted-queries', 'Automatic Persisted Queries'],
+ ['response-caching', 'Response Caching'],
],
},
integrations: {
diff --git a/website/v3/docs/features/response-caching.mdx b/website/v3/docs/features/response-caching.mdx
new file mode 100644
index 0000000000..272465c705
--- /dev/null
+++ b/website/v3/docs/features/response-caching.mdx
@@ -0,0 +1,201 @@
+---
+id: response-caching
+title: Response Caching
+sidebar_label: Resposne Caching
+---
+
+Response caching is a technique for reducing server load by caching GraphQL query operation results.
+
+## Installation
+
+
+
+## Quick Start
+
+```ts
+import { createYoga } from 'graphql-yoga'
+import { createServer } from 'node:http'
+import { useResponseCache } from '@graphql-yoga/plugin-response-cache'
+
+const yoga = createYoga({
+ schema: {
+ typeDefs: `type Query { slow: String}`,
+ resolvers: {
+ Query: {
+ slow: async () => {
+ await new Promise((resolve) => setTimeout(resolve, 5000))
+ return 'I am slow.'
+ },
+ },
+ },
+ },
+ plugins: [
+ useResponseCache({
+ // global cache
+ session: () => null,
+ }),
+ ],
+})
+
+const server = createServer(yoga)
+server.listen(4000)
+```
+
+```
+curl -X POST -H 'Content-Type: application/json' http://localhost:4000/graphql \
+-d '{"query":"{__typename}"}' -w '\nTotal time : %{time_total}'
+```
+
+This will output something like the following:
+
+```
+{"data":{"slow":"I am slow."}}
+Total time:5.026632
+```
+
+After executing the same curl statement a second time, the duration is significantly lower.
+
+```
+{"data":{"slow":"I am slow."}}
+Total time:0.007571%
+```
+
+## Session based caching
+
+If your GraphQL API returns specific data depending on the viewer's session, you can use the `session` option to cache the response per session.
+
+```ts
+useResponseCache({
+ // cache based on the authentication header
+ session: (request) => request.headers.get('authentication'),
+})
+```
+
+## TTL
+
+It is possible to give cached operations a time to live. Either globally, based on [schema coordinates](https://github.com/graphql/graphql-wg/blob/main/rfcs/SchemaCoordinates.md) or object types.
+If a query operation result contains multiple objects of the same type, the lowest TTL is picked.
+
+```ts
+useResponseCache({
+ session: () => null,
+ // by default cache all operations for 2 seconds
+ ttl: 2_000,
+ ttlPerType: {
+ // only cache query operations containing User for 500ms
+ User: 500,
+ },
+ ttlPerSchemaCoordinate: {
+ // cache operations selecting Query.lazy for 10 seconds
+ 'Query.lazy': 10_000,
+ },
+})
+```
+
+## Invalidatios via Mutation
+
+When executing a mutation operation the cached query results that contain type entities within the Mutation result will be automatically be invalidated.
+
+```graphql
+mutation {
+ updateUser(id: 1, newName: "John") {
+ __typename
+ id
+ name
+ }
+}
+```
+
+```json
+{
+ "data": {
+ "updateLaunch": {
+ "__typename": "User",
+ "id": "1",
+ "name": "John"
+ }
+ }
+}
+```
+
+All cached query results that contain the type `User` with the id `1` will be invalidated.
+
+This behavior can be disabled by setting the `invalidateViaMutation` option to `false`.
+
+```ts
+useResponseCache({
+ session: (request) => null,
+ invalidateViaMutation: false,
+})
+```
+
+## Manual Invalidation
+
+You can invalidate a type or specific instances of a type using the cache invalidation API.
+
+In order to use the API, you need to manually instantiate the cache an pass it to the `useResponseCache` plugin.
+
+```ts
+import {
+ useResponseCache,
+ createInMemoryCache,
+} from '@graphql-yoga/plugin-response-cache'
+
+const cache = createInMemoryCache()
+
+useResponseCache({
+ session: () => null,
+ cache,
+})
+```
+
+Then in your business logic you can call the `invalidate` method on the cache instance.
+
+Invalidate all GraphQL query results that referance a specific type:
+
+```ts
+cache.invalidate([{ type: 'User' }])
+```
+
+Invalidate all GraphQL query results that reference a specific entity of a type:
+
+```ts
+cache.invalidate([{ type: 'User', id: '1' }])
+```
+
+Invalidate all GraphQL query results multiple entities in a single call.
+
+```ts
+cache.invalidate([
+ { type: 'Post', id: '1' },
+ { type: 'User', id: '2' },
+])
+```
+
+## External Cache
+
+By default the response cache stores all the cached query results in memory.
+
+If you want a cache that is shared between multiple server instances you can use the Redis cache implementation.
+
+
+
+```ts
+import { useResponseCache } from '@graphql-yoga/plugin-response-cache'
+import Redis from 'ioredis'
+
+const redis = new Redis({
+ host: 'my-redis-db.example.com',
+ port: '30652',
+ password: '1234567890',
+})
+
+const redis = new Redis('rediss://:1234567890@my-redis-db.example.com:30652')
+
+const cache = createRedisCache({ redis })
+
+useResponseCache({
+ session: () => null,
+ cache,
+})
+```