diff --git a/cspell-dict.txt b/cspell-dict.txt
index 71fe67c7204..cde7791f02a 100644
--- a/cspell-dict.txt
+++ b/cspell-dict.txt
@@ -31,6 +31,7 @@ Changesets
cimg
circleci
cleartext
+CNCF
codecov
codegen
codepaths
@@ -181,6 +182,7 @@ sumby
supergraph
Supergraph
supergraphs
+technotes
testful
testonly
testsuite
diff --git a/docs/source/api/plugin/cache-control.mdx b/docs/source/api/plugin/cache-control.mdx
index 4ed20fe1f91..e2652da85ea 100644
--- a/docs/source/api/plugin/cache-control.mdx
+++ b/docs/source/api/plugin/cache-control.mdx
@@ -1,5 +1,5 @@
---
-title: "API Reference: Cache control plugin"
+title: "API Reference: Cache Control Plugin"
api_reference: true
---
diff --git a/docs/source/api/plugin/drain-http-server.mdx b/docs/source/api/plugin/drain-http-server.mdx
index 212bd3a3fc4..8b56e6713ea 100644
--- a/docs/source/api/plugin/drain-http-server.mdx
+++ b/docs/source/api/plugin/drain-http-server.mdx
@@ -1,5 +1,5 @@
---
-title: 'API Reference: Drain HTTP server plugin'
+title: 'API Reference: Drain HTTP Server Plugin'
api_reference: true
---
diff --git a/docs/source/api/plugin/inline-trace.mdx b/docs/source/api/plugin/inline-trace.mdx
index 5a4c653be66..e36925193df 100644
--- a/docs/source/api/plugin/inline-trace.mdx
+++ b/docs/source/api/plugin/inline-trace.mdx
@@ -1,5 +1,5 @@
---
-title: "API Reference: Inline trace plugin"
+title: "API Reference: Inline Trace Plugin"
api_reference: true
---
diff --git a/docs/source/api/plugin/landing-pages.mdx b/docs/source/api/plugin/landing-pages.mdx
index 53f89d46020..a96c03b9745 100644
--- a/docs/source/api/plugin/landing-pages.mdx
+++ b/docs/source/api/plugin/landing-pages.mdx
@@ -1,5 +1,5 @@
---
-title: "API Reference: Landing page plugins"
+title: "API Reference: Landing Page Plugins"
api_reference: true
---
diff --git a/docs/source/api/plugin/schema-reporting.mdx b/docs/source/api/plugin/schema-reporting.mdx
index bbc8e87d129..83cc5638b63 100644
--- a/docs/source/api/plugin/schema-reporting.mdx
+++ b/docs/source/api/plugin/schema-reporting.mdx
@@ -1,16 +1,16 @@
---
-title: "API Reference: Schema reporting plugin"
+title: "API Reference: Schema Reporting Plugin"
api_reference: true
---
> Note:
-> **The schema reporting plugin does not support graphs that use Apollo Federation.** If you are using Federation, or if you want to publish your monolith schema in your CI/CD pipeline, you can use the [Rover CLI to publish your schema or subgraph changes](/graphos/schema/cli-registration).
+> **The schema reporting plugin does not support graphs that use Apollo Federation.** If you are using Federation, or if you want to publish your monolith schema in your CI/CD pipeline, you can use the [Rover CLI to publish your schema or subgraph changes](/graphos/delivery/publishing-schemas).
## Using the plugin
This article documents the options for the `ApolloServerPluginSchemaReporting` plugin, which you can import from `@apollo/server/plugin/schemaReporting`.
-This plugin enables your GraphQL server to register its latest schema with the Apollo schema registry every time it starts up. Full details on schema reporting can be found in [the Apollo Studio docs](/studio/schema/schema-reporting/).
+This plugin enables your GraphQL server to register its latest schema with the Apollo schema registry every time it starts up. Full details on schema reporting can be found in [the Apollo Studio docs](/graphos/delivery/publishing-schemas).
In order to use this plugin, you must configure your server with a graph API key, either with the `APOLLO_KEY` environment variable or by passing it directly to your `ApolloServer` constructor (e.g., `new ApolloServer({apollo: {key: KEY}})`). This is the same way you configure [usage reporting](./usage-reporting).
diff --git a/docs/source/api/plugin/subscription-callback.mdx b/docs/source/api/plugin/subscription-callback.mdx
index 8a3afc0e2b6..69945eebb6a 100644
--- a/docs/source/api/plugin/subscription-callback.mdx
+++ b/docs/source/api/plugin/subscription-callback.mdx
@@ -1,5 +1,5 @@
---
-title: "API Reference: Subscription callback plugin"
+title: "API Reference: Subscription Callback Plugin"
api_reference: true
minVersion: 4.9.0
---
diff --git a/docs/source/api/plugin/usage-reporting.mdx b/docs/source/api/plugin/usage-reporting.mdx
index d715f8690b1..bbcdb84a9ab 100644
--- a/docs/source/api/plugin/usage-reporting.mdx
+++ b/docs/source/api/plugin/usage-reporting.mdx
@@ -1,10 +1,10 @@
---
-title: "API Reference: Usage reporting plugin"
+title: "API Reference: Usage Reporting Plugin"
api_reference: true
---
-> Sending metrics from Apollo Server to GraphOS requires an [enterprise plan](../org/plans/).
-> If your organization _doesn't_ currently have an Enterprise plan, you can test out this functionality by signing up for a free [Enterprise trial](https://studio.apollographql.com/signup?type=enterprise-trial&referrer=docs-content).
+> Sending metrics from Apollo Server to GraphOS requires an [Enterprise plan](https://www.apollographql.com/pricing).
+> If your organization doesn't have an Enterprise plan, you can test out this functionality by signing up for a free [GraphOS trial](https://studio.apollographql.com/signup?referrer=docs-content).
Apollo Server's built-in usage reporting plugin gathers data on how your clients use the operations and fields in your GraphQL schema. The plugin also handles pushing this usage data to [GraphOS](/graphos/), as described in [Metrics and logging](../../monitoring/metrics/).
@@ -147,7 +147,7 @@ Providing a number `x` is equivalent to passing this function:
* The operation _doesn't_ produce a trace that can be viewed in the Traces section of the Operations page in Studio.
* The operation _does_ still contribute to most features of Studio, such as schema checks, the Operations page, and the "referencing operations" statistic on the Fields page.
-(For more information about the difference between the "referencing operations" and "field executions" statistics, see [the Studio Fields page documentation](https://apollographql.com/docs/studio/metrics/field-usage/).)
+(For more information about the difference between the "referencing operations" and "field executions" statistics, see [the Studio Fields page documentation](/graphos/metrics/field-usage).)
Returning `false` (or `0`) for some or all operations can improve your server's performance, because calculating complete traces can introduce significant overhead. This is especially true for a federated graph, because traces are transmitted from the subgraph to the Gateway in-band inside the actual GraphQL response.
diff --git a/docs/source/builtin-plugins.md b/docs/source/builtin-plugins.md
index 113ba53798d..8069d8c2adc 100644
--- a/docs/source/builtin-plugins.md
+++ b/docs/source/builtin-plugins.md
@@ -1,5 +1,5 @@
---
-title: Built-in plugins
+title: Built-In Plugins
---
**Plugins** extend Apollo Server's functionality by performing custom operations in response to certain events. These events correspond to individual phases of the GraphQL request lifecycle, and to the lifecycle of Apollo Server itself.
diff --git a/docs/source/config.json b/docs/source/config.json
index 8b7f40658c9..8e4be099ff7 100644
--- a/docs/source/config.json
+++ b/docs/source/config.json
@@ -7,22 +7,22 @@
],
"sidebar": {
"Introduction": "/",
- "Get started": "/getting-started",
+ "Get Started": "/getting-started",
"New in v4": {
"Migrating to Apollo Server 4": "/migration",
- "Previous versions": "/previous-versions",
+ "Previous Versions": "/previous-versions",
"Changelog": "https://github.com/apollographql/apollo-server/blob/main/packages/server/CHANGELOG.md"
},
"Defining a Schema": {
- "Schema basics": "/schema/schema",
- "Unions and interfaces": "/schema/unions-interfaces",
- "Custom scalars": "/schema/custom-scalars",
+ "Schema Basics": "/schema/schema",
+ "Unions and Interfaces": "/schema/unions-interfaces",
+ "Custom Scalars": "/schema/custom-scalars",
"Directives": "/schema/directives"
},
"Resolving Operations": {
"Resolvers": "/data/resolvers",
- "Sharing context": "/data/context",
- "Error handling": "/data/errors",
+ "Sharing Context": "/data/context",
+ "Error Handling": "/data/errors",
"Subscriptions": "/data/subscriptions"
},
"Fetching Data": {
@@ -31,35 +31,35 @@
},
"Web Frameworks": {
"Integrations": "/integrations/integration-index",
- "Building integrations": "/integrations/building-integrations",
- "MERN stack tutorial": "/integrations/mern"
+ "Building Integrations": "/integrations/building-integrations",
+ "MERN Stack Tutorial": "/integrations/mern"
},
"Development Workflow": {
- "Build and run queries": "/workflow/build-run-queries",
- "Request format": "/workflow/requests",
- "Generating TS types": "/workflow/generate-types",
+ "Build and Run Queries": "/workflow/build-run-queries",
+ "Request Format": "/workflow/requests",
+ "Generating TS Types": "/workflow/generate-types",
"Mocking": "/testing/mocking",
- "Integration testing": "/testing/testing",
- "Apollo Studio Explorer": "https://www.apollographql.com/docs/studio/explorer/"
+ "Integration Testing": "/testing/testing"
},
"Performance": {
"Caching": "/performance/caching",
- "Cache backends": "/performance/cache-backends",
- "Automatic persisted queries": "/performance/apq"
+ "Cache Backends": "/performance/cache-backends",
+ "Response Cache Eviction": "/performance/response-cache-eviction",
+ "Automatic Persisted Queries": "/performance/apq"
},
"Security": {
- "Auth": "/security/authentication",
+ "Authentication and Authorization": "/security/authentication",
"CORS": "/security/cors",
"Terminating SSL": "/security/terminating-ssl",
- "Proxy configuration": "/security/proxy-configuration"
+ "Proxy Configuration": "/security/proxy-configuration"
},
"Deployment": {
"Lambda": "/deployment/lambda",
"Heroku": "/deployment/heroku"
},
"Monitoring": {
- "Metrics and logging": "/monitoring/metrics",
- "Health checks": "/monitoring/health-checks"
+ "Metrics and Logging": "/monitoring/metrics",
+ "Health Checks": "/monitoring/health-checks"
},
"API Reference": {
"ApolloServer": "/api/apollo-server",
@@ -68,28 +68,29 @@
},
"Plugins": {
"Overview": "/builtin-plugins",
- "Built-in": {
- "Usage reporting": "/api/plugin/usage-reporting",
- "Schema reporting": "/api/plugin/schema-reporting",
- "Inline trace": "/api/plugin/inline-trace",
- "Drain HTTP server": "/api/plugin/drain-http-server",
- "Cache control": "/api/plugin/cache-control",
- "Landing pages": "/api/plugin/landing-pages",
- "Federated subscriptions": "/api/plugin/subscription-callback"
+ "Built-In": {
+ "Usage Reporting": "/api/plugin/usage-reporting",
+ "Schema Reporting": "/api/plugin/schema-reporting",
+ "Inline Trace": "/api/plugin/inline-trace",
+ "Drain HTTP Server": "/api/plugin/drain-http-server",
+ "Cache Control": "/api/plugin/cache-control",
+ "Landing Pages": "/api/plugin/landing-pages",
+ "Federated Subscriptions": "/api/plugin/subscription-callback"
},
"Custom": {
- "Creating plugins": "/integrations/plugins",
- "Event reference": "/integrations/plugins-event-reference"
+ "Creating Plugins": "/integrations/plugins",
+ "Event Reference": "/integrations/plugins-event-reference"
}
},
"Using with Federation": {
- "As a subgraph": {
+ "As a Subgraph": {
"Setup": "/using-federation/apollo-subgraph-setup",
"@apollo/subgraph reference": "/using-federation/api/apollo-subgraph/"
},
- "As a gateway": {
+ "As a Gateway": {
"Setup": "/using-federation/apollo-gateway-setup",
- "@apollo/gateway reference": "/using-federation/api/apollo-gateway/"
+ "Performance Optimizations": "/using-federation/gateway-performance",
+ "@apollo/gateway Reference": "/using-federation/api/apollo-gateway/"
}
}
}
diff --git a/docs/source/data/errors.mdx b/docs/source/data/errors.mdx
index f7df300ab25..ee21fe1b503 100644
--- a/docs/source/data/errors.mdx
+++ b/docs/source/data/errors.mdx
@@ -1,5 +1,5 @@
---
-title: Error handling
+title: Error Handling
description: Making errors actionable on the client and server
---
diff --git a/docs/source/data/fetching-data.mdx b/docs/source/data/fetching-data.mdx
index 568a553f74f..f1d82044479 100644
--- a/docs/source/data/fetching-data.mdx
+++ b/docs/source/data/fetching-data.mdx
@@ -1,5 +1,5 @@
---
-title: Fetching data
+title: Fetching Data
description: Manage connections to databases and other data sources
---
@@ -26,6 +26,12 @@ flowchart LR;
client --Sends query--> ApolloServer;
```
+
+
+[Learn how Apollo Connectors](/graphos/schema-design/connectors/) simplify incorporating REST APIs into your graph.
+
+
+
Because your server can use multiple various data sources, keeping your [resolvers](./resolvers) tidy becomes _even more_ important.
For this reason, we recommend creating individual data source classes to encapsulate the logic of fetching data from a particular source, providing methods that resolvers can use to access data neatly. You can additionally customize your data source classes to help with caching, deduplication, or errors while resolving operations.
diff --git a/docs/source/data/fetching-rest.mdx b/docs/source/data/fetching-rest.mdx
index 8963290cc26..4d092d51d9b 100644
--- a/docs/source/data/fetching-rest.mdx
+++ b/docs/source/data/fetching-rest.mdx
@@ -5,6 +5,12 @@ description: Using RESTDataSource to fetch data from REST APIs
import TopLevelAwait from "../shared/top-level-await.mdx"
+
+
+[Learn how Apollo Connectors](/graphos/schema-design/connectors/) simplify incorporating REST APIs into your graph.
+
+
+
> See the [`@apollo/datasource-rest` README](https://github.com/apollographql/datasource-rest) for the full details of the `RESTDataSource` API.
The `RESTDataSource` class simplifies fetching data from REST APIs and helps handle caching, request deduplication, and errors while resolving operations.
diff --git a/docs/source/data/resolvers.mdx b/docs/source/data/resolvers.mdx
index 0e551a6391c..a83cacae122 100644
--- a/docs/source/data/resolvers.mdx
+++ b/docs/source/data/resolvers.mdx
@@ -483,4 +483,4 @@ See [Resolving Entities](https://www.apollographql.com/docs/federation/entities/
As with all code, a resolver's performance depends on its logic. It's important to understand which of your schema's fields are computationally expensive or otherwise slow to resolve, so that you can either improve their performance or make sure you only query them when necessary.
-[Apollo Studio](https://www.apollographql.com/docs/studio/) integrates directly with Apollo Server to provide field-level metrics that help you understand the performance of your graph over time. For more information, see [Analyzing performance](https://www.apollographql.com/docs/studio/performance/).
+[Apollo Studio](https://studio.apollographql.com) integrates directly with Apollo Server to provide field-level metrics that help you understand the performance of your graph over time. For more information, see [Analyzing performance](https://www.apollographql.com/docs/graphos/platform/insights/field-usage).
diff --git a/docs/source/getting-started.mdx b/docs/source/getting-started.mdx
index aa292e31e80..6e24b993b06 100644
--- a/docs/source/getting-started.mdx
+++ b/docs/source/getting-started.mdx
@@ -1,5 +1,5 @@
---
-title: Get started with Apollo Server
+title: Get Started with Apollo Server
description: ''
---
diff --git a/docs/source/index.mdx b/docs/source/index.mdx
index a6b11e680f8..b34bdac4236 100644
--- a/docs/source/index.mdx
+++ b/docs/source/index.mdx
@@ -4,7 +4,7 @@ title: Introduction to Apollo Server
> đź“Ł **Apollo Server 4 is generally available!**
>
-> [See what's new](./migration/)!
+> [See what's new](/apollo-server/migration/)!
>
> Docs for Apollo Server 3 are [available here](/apollo-server/v3/).
@@ -14,8 +14,8 @@ title: Introduction to Apollo Server
#### You can use Apollo Server as:
-* The GraphQL server for a [subgraph](./using-federation/apollo-subgraph-setup) in a federated supergraph
-* An add-on to any new or existing Node.js apps—this includes apps running on [Express](./api/express-middleware) (including [MERN stack](./integrations/mern) apps), [AWS Lambda](https://www.npmjs.com/package/@as-integrations/aws-lambda), [Azure Functions](https://www.npmjs.com/package/@as-integrations/azure-functions), [Cloudflare](https://www.npmjs.com/package/@as-integrations/cloudflare-workers), [Fastify](https://www.npmjs.com/package/@as-integrations/fastify), and [more](./integrations/integration-index)
+* The GraphQL server for a [subgraph](/apollo-server/using-federation/apollo-subgraph-setup) in a federated supergraph
+* An add-on to any new or existing Node.js apps—this includes apps running on [Express](/apollo-server/api/express-middleware) (including [MERN stack](/apollo-server/integrations/mern) apps), [AWS Lambda](https://www.npmjs.com/package/@as-integrations/aws-lambda), [Azure Functions](https://www.npmjs.com/package/@as-integrations/azure-functions), [Cloudflare](https://www.npmjs.com/package/@as-integrations/cloudflare-workers), [Fastify](https://www.npmjs.com/package/@as-integrations/fastify), and [more](/apollo-server/integrations/integration-index)
#### Apollo Server provides:
@@ -27,7 +27,7 @@ title: Introduction to Apollo Server
#### Ready to try it out?
-
+
Get started!
diff --git a/docs/source/integrations/mern.mdx b/docs/source/integrations/mern.mdx
index b9f1e084709..db9ab9e6205 100644
--- a/docs/source/integrations/mern.mdx
+++ b/docs/source/integrations/mern.mdx
@@ -1,5 +1,5 @@
---
-title: Teaching the MERN stack to speak GraphQL
+title: Teaching the MERN Stack to Speak GraphQL
---
Apollo Server is designed to work seamlessly with MERN stack (MongoDB, Express, React, Node) applications. This tutorial shows how to add Apollo Server to an existing MERN stack project. Specifically, this tutorial demonstrates how to:
@@ -22,7 +22,7 @@ In your server folder, run the following command to install these packages and s
your server project's `node_modules` directory:
```bash
- npm install graphql graphql-tag @apollo/subgraph @apollo/server
+ npm install graphql graphql-tag @apollo/subgraph @apollo/server
```
- [`graphql`](https://www.npmjs.com/package/graphql) is the JavaScript reference implementation for GraphQL
diff --git a/docs/source/integrations/plugins-event-reference.mdx b/docs/source/integrations/plugins-event-reference.mdx
index e6a10614268..2bdc96991c5 100644
--- a/docs/source/integrations/plugins-event-reference.mdx
+++ b/docs/source/integrations/plugins-event-reference.mdx
@@ -1,5 +1,5 @@
---
-title: Apollo Server plugin event reference
+title: Apollo Server Plugin Event Reference
---
> All plugin lifecycle methods are `async`, _except for [`willResolveField`](#willresolvefield) and [`schemaDidLoadOrUpdate`](#schemadidloadorupdate)_.
diff --git a/docs/source/integrations/plugins.mdx b/docs/source/integrations/plugins.mdx
index 3e66d62f214..a0b5e8c3d4b 100644
--- a/docs/source/integrations/plugins.mdx
+++ b/docs/source/integrations/plugins.mdx
@@ -1,5 +1,5 @@
---
-title: Creating Apollo Server plugins
+title: Creating Apollo Server Plugins
description: Extend Apollo Server with custom functionality
---
diff --git a/docs/source/monitoring/health-checks.mdx b/docs/source/monitoring/health-checks.mdx
index 98697b9efb8..17fa268103f 100644
--- a/docs/source/monitoring/health-checks.mdx
+++ b/docs/source/monitoring/health-checks.mdx
@@ -1,5 +1,5 @@
---
-title: Health checks
+title: Health Checks
description: Determining the health status of Apollo Server
---
diff --git a/docs/source/monitoring/metrics.mdx b/docs/source/monitoring/metrics.mdx
index c73398337c6..f79dfe2fa95 100644
--- a/docs/source/monitoring/metrics.mdx
+++ b/docs/source/monitoring/metrics.mdx
@@ -1,10 +1,10 @@
---
-title: Metrics and logging
+title: Metrics and Logging
description: How to monitor Apollo Server's performance
---
-> Sending metrics from Apollo Server to GraphOS requires an [enterprise plan](../org/plans/).
-> If your organization _doesn't_ currently have an Enterprise plan, you can test out this functionality by signing up for a free [Enterprise trial](https://studio.apollographql.com/signup?type=enterprise-trial&referrer=docs-content).
+> Sending metrics from Apollo Server to GraphOS requires an [Enterprise plan](https://www.apollographql.com/pricing).
+> If your organization doesn't have an Enterprise plan, you can test out this functionality by signing up for a free [GraphOS trial](https://studio.apollographql.com/signup?referrer=docs-content).
Apollo Server integrates seamlessly with [Apollo GraphOS](/graphos/) to help you monitor the execution of your GraphQL operations. Apollo Server additionally provides configurable mechanisms for logging each phase of a GraphQL operation.
@@ -12,7 +12,7 @@ Apollo Server integrates seamlessly with [Apollo GraphOS](/graphos/) to help you
## Sending metrics to GraphOS
-[Apollo GraphOS](/graphos/) provides an integrated hub for all of your GraphQL performance data, which you can view in Apollo Studio. Studio [aggregates and displays information](/graphos/metrics/) for your schema, queries, requests, and errors. You can also configure alerts that support [Slack](/graphos/metrics/notifications/notification-setup/#slack) and [Datadog](/graphos/metrics/datadog-integration/) integrations.
+[Apollo GraphOS](/graphos/) provides an integrated hub for all of your GraphQL performance data, which you can view in Apollo Studio. Studio [aggregates and displays information](/graphos/metrics/) for your schema, queries, requests, and errors. You can also configure alerts that support [Slack](/graphos/metrics/notifications/performance-alerts#slack) and [Datadog](/graphos/metrics/datadog-integration) integrations.
### Connecting to GraphOS
diff --git a/docs/source/performance/apq.md b/docs/source/performance/apq.md
index f470be9fe18..64f111b4628 100644
--- a/docs/source/performance/apq.md
+++ b/docs/source/performance/apq.md
@@ -1,5 +1,5 @@
---
-title: Automatic persisted queries
+title: Automatic Persisted Queries
description: Improve network performance by sending smaller requests
---
diff --git a/docs/source/performance/cache-backends.mdx b/docs/source/performance/cache-backends.mdx
index 0392a92e5ab..b296f822254 100644
--- a/docs/source/performance/cache-backends.mdx
+++ b/docs/source/performance/cache-backends.mdx
@@ -1,5 +1,5 @@
---
-title: Configuring cache backends
+title: Configuring Cache Backends
description: How to configure Apollo Server's cache
---
diff --git a/docs/source/performance/caching.md b/docs/source/performance/caching.md
index 89095c0cc2b..315070d14c3 100644
--- a/docs/source/performance/caching.md
+++ b/docs/source/performance/caching.md
@@ -1,5 +1,5 @@
---
-title: Server-side caching
+title: Server-Side Caching
description: Configure caching behavior on a per-field basis
---
diff --git a/docs/source/performance/response-cache-eviction.mdx b/docs/source/performance/response-cache-eviction.mdx
new file mode 100644
index 00000000000..53e2ff9c4f7
--- /dev/null
+++ b/docs/source/performance/response-cache-eviction.mdx
@@ -0,0 +1,140 @@
+---
+title: Response Cache Eviction
+subtitle: Advanced cache eviction patterns using custom cache keys
+description: Use advanced cache eviction patterns with custom cache keys to selectively evict cached responses when relevant events occur.
+published: 2022-08-10
+id: TN0010
+redirectFrom:
+ - /technotes/TN0011-response-cache-eviction/
+---
+
+
+
+For a runnable example of this cache eviction solution, see the [Response Cache Eviction](https://github.com/apollosolutions/response-cache-eviction) repo.
+
+
+
+Apollo Server's Full Response Cache plugin (`@apollo/server-plugin-response-cache`) caches the results of operations for a period of time (time-to-live or TTL). After that time expires, the results are evicted from the cache, and the server fully resolves the operation the next time a client executes it.
+
+The most straightforward way to avoid stale data in the response cache is to set a short default TTL. However, this limits the cache's effectiveness for responses that rarely (or never) change.
+
+The Full Response Cache plugin supports advanced cache eviction patterns via custom cache keys in versions `3.7.0` and later. This enables you to set a longer default TTL and increase the cache's hit rate, because you can selectively evict cached responses when relevant events occur.
+
+## Customizing the cache key
+
+This works by defining a custom response cache key by a pattern that can later be searched on in the cache. What this key should be comprised of and how it should be structured depends on the use-case and what search patterns our cache implementation supports.
+
+### Ensuring cache key uniqueness
+
+Keep in mind that each key links to a full response object, so if your key is too generic, you risk potentially returning the wrong data for queries. For example, generating a cache key based solely on the operation name would yield the same responses for all operations with the same name, even if the entire query is different. Make sure your keys are unique for each execution of the incoming operations that returns different data.
+
+### Defining a custom cache key
+
+As noted above, the `3.7.0` of the Full Response Cache plugin introduced the `generateCacheKey` configuration method. The response from this function will be used as the cache key to store the current query response.
+
+Here's the method signature:
+
+```typescript
+generateCacheKey(
+ requestContext: GraphQLRequestContext>,
+ keyData: unknown,
+): string;
+```
+
+The [`requestContext`](https://github.com/apollographql/apollo-server/blob/578dc68831d93d5809b78174d6179c10afc8c2ef/packages/server/src/externalTypes/requestPipeline.ts#L38) parameter holds data about the running GraphQL request, such as the request / response objects as well as the [context object](/apollo-server/v3/data/resolvers/#the-context-argument) that is passed to your resolver functions. Any portion of these data objects can be used as part of your cache key.
+
+The `keyData` parameter can be used to ensure the uniqueness of your key. In most cases, hashing this variable should be enough to generate a unique key per operation. In fact, the [default implementation](https://github.com/apollographql/apollo-server/blob/578dc68831d93d5809b78174d6179c10afc8c2ef/packages/plugin-response-cache/src/ApolloServerPluginResponseCache.ts#L182) hashes a `JSON.stringify` version of this parameter as the cache key.
+
+In this example, we prefix the default key with the name of the incoming operation:
+
+```typescript
+import { createHash } from 'crypto';
+
+function sha(s: string) {
+ return createHash('sha256').update(s).digest('hex');
+}
+
+generateCacheKey(requestContext, keyData) {
+ const operationName = requestContext.request.operationName ?? 'unnamed';
+ const key = operationName + ':' + sha(JSON.stringify(keyData));
+ return key;
+}
+```
+
+An example key for the named operation “MyOpName”:
+
+```bash showLineNumbers=false
+keyv:fqc:MyOpName:e7eed80930547ed4ab4ece81a18955967831ff4c40757eda9bf1f0de84e042f8
+```
+
+This approach ensures that all cache keys are unique enough to store unique responses, but gives us a pattern we can use to selectively remove cache entries based on our operation names.
+
+## Evicting cache entries
+
+There are two main strategies for evicting response cache entries: manually evicting from a shell prompt, or in response to some event, like a mutation.
+
+Actually removing entries from the cache once a custom cache key is being used will depend on your caching backend, as each offer different ways to list and remove keys. We'll explore both options using Redis.
+
+### Evicting manually
+
+If you need to evict cache entries for local testing or debugging, it might suffice to define a custom cache key pattern and delete entries as needed with `redis-cli`.
+
+Here's an example of removing all keys in a Redis instance that match a given pattern:
+
+```bash showLineNumbers=false
+redis-cli --raw KEYS "$PATTERN" | xargs redis-cli del
+```
+
+This command lists every key matching any glob-style "$PATTERN" and removes them one by one.
+
+Here's an example using the operation name prefix pattern described above to remove all entries with unnamed operations:
+
+```bash showLineNumbers=false
+redis-cli --raw KEYS "keyv:fqc:unnamed*" | xargs redis-cli del
+```
+
+[The Redis docs for the KEYS command](https://redis.io/commands/keys/) recommend NOT using the `KEYS` function in production application code and only executing against production with "extreme care." Redis specifically recommends instead using `SCAN`, which is described in [Event-based eviction](#event-based-eviction).
+
+The utility of this approach will depend on the number of records stored in your cache and how performant the pattern search is, as well as the number of records that need to be removed. If your searches are scanning and/or returning millions of records, this approach probably should be avoided in a production environment.
+
+### Event-based eviction
+
+Most other use cases need to evict cache entries in response to certain events. The [Response Cache Eviction](https://github.com/apollosolutions/response-cache-eviction) repo provides a full walkthrough of evicting certain operation responses from the cache when a specific mutation is executed.
+
+Redis clients currently offer no way to batch delete entries based on a pattern. As a result, our event based solution needs to do a similar algorithm: look up keys by a pattern, then remove those keys.
+
+The following snippet is from [the repo mentioned above](https://github.com/apollosolutions/response-cache-eviction):
+
+```ts
+import {createClient, RedisClientType} from 'redis';
+
+const deleteByPrefix = async (prefix: string) => {
+ const client = createClient({url: 'redis://localhost:6379'});
+ await client.connect();
+
+ const scanIterator = client.scanIterator({
+ MATCH: `keyv:fqc:${prefix}*`,
+ COUNT: 2000
+ });
+
+ let keys = [];
+
+ for await (const key of scanIterator) {
+ keys.push(key);
+ }
+
+ if (keys.length > 0) {
+ await client.del(keys); // This is blocking, consider handling async in production if the number of keys is large
+ }
+
+ return keys;
+};
+```
+
+This solution uses the `scanIterator` function (which uses the `SCAN` Redis function) to scan through cache entries in a memory-efficient way, as opposed to the `KEYS` method mentioned above. The `SCAN` method is more appropriate to use in a production environment.
+
+The `deleteByPrefix` method can be added to your context object and then executed in your mutation resolvers to remove certain operations from the cache.
+
+## Final thoughts
+
+Either of the eviction solutions mentioned above should be used with caution. Make sure you have an understanding of the sorts of effects that your setup will have on your cache. Its a good idea to monitor your caching server when testing your different use cases to ensure that you aren't overloading your cache.
diff --git a/docs/source/previous-versions.mdx b/docs/source/previous-versions.mdx
index 1dd6863b9d6..657f9d6418d 100644
--- a/docs/source/previous-versions.mdx
+++ b/docs/source/previous-versions.mdx
@@ -1,5 +1,5 @@
---
-title: Previous versions of Apollo Server
+title: Previous Versions of Apollo Server
---
## Apollo Server 4 is generally available
diff --git a/docs/source/schema/custom-scalars.mdx b/docs/source/schema/custom-scalars.mdx
index 5c6ebeedd3a..7cedb2a80e2 100644
--- a/docs/source/schema/custom-scalars.mdx
+++ b/docs/source/schema/custom-scalars.mdx
@@ -1,5 +1,5 @@
---
-title: Custom scalars
+title: Custom Scalars
---
import TopLevelAwait from "../shared/top-level-await.mdx"
diff --git a/docs/source/schema/schema.md b/docs/source/schema/schema.md
index 7cf406c0407..d7139ad11ec 100644
--- a/docs/source/schema/schema.md
+++ b/docs/source/schema/schema.md
@@ -1,5 +1,5 @@
---
-title: GraphQL schema basics
+title: GraphQL Schema Basics
---
Your GraphQL server uses a **schema** to describe the shape of your available data. This schema defines a hierarchy of **types** with **fields** that are populated from your back-end data stores. The schema also specifies exactly which **queries** and **mutations** are available for clients to execute.
diff --git a/docs/source/schema/unions-interfaces.md b/docs/source/schema/unions-interfaces.md
index 191ae5f2c9d..ae233110ec5 100644
--- a/docs/source/schema/unions-interfaces.md
+++ b/docs/source/schema/unions-interfaces.md
@@ -1,5 +1,5 @@
---
-title: Unions and interfaces
+title: Unions and Interfaces
description: Abstract schema types
---
diff --git a/docs/source/security/authentication.mdx b/docs/source/security/authentication.mdx
index 93db4777e3c..95f66253ba0 100644
--- a/docs/source/security/authentication.mdx
+++ b/docs/source/security/authentication.mdx
@@ -1,5 +1,5 @@
---
-title: Authentication and authorization
+title: Authentication and Authorization
description: Control access to your GraphQL API
---
diff --git a/docs/source/security/proxy-configuration.md b/docs/source/security/proxy-configuration.md
index 866e6fa6634..1b35559c307 100644
--- a/docs/source/security/proxy-configuration.md
+++ b/docs/source/security/proxy-configuration.md
@@ -1,5 +1,5 @@
---
-title: Proxy configuration
+title: Proxy Configuration
description: Configuring proxy settings for outgoing requests
---
diff --git a/docs/source/testing/testing.mdx b/docs/source/testing/testing.mdx
index 4eb62d199e9..ac61506fcdd 100644
--- a/docs/source/testing/testing.mdx
+++ b/docs/source/testing/testing.mdx
@@ -1,5 +1,5 @@
---
-title: Integration testing
+title: Integration Testing
description: Utilities for testing Apollo Server
---
diff --git a/docs/source/using-federation/apollo-gateway-setup.mdx b/docs/source/using-federation/apollo-gateway-setup.mdx
index 3ccd1b556b0..e10c9723922 100644
--- a/docs/source/using-federation/apollo-gateway-setup.mdx
+++ b/docs/source/using-federation/apollo-gateway-setup.mdx
@@ -1,5 +1,5 @@
---
-title: Implementing a gateway with Apollo Server
+title: Implementing a Gateway with Apollo Server
description: Using a Node.js gateway as your graph router
---
diff --git a/docs/source/using-federation/apollo-subgraph-setup.mdx b/docs/source/using-federation/apollo-subgraph-setup.mdx
index 1bfbc9346f1..e58a4f1f043 100644
--- a/docs/source/using-federation/apollo-subgraph-setup.mdx
+++ b/docs/source/using-federation/apollo-subgraph-setup.mdx
@@ -1,5 +1,5 @@
---
-title: Implementing a subgraph with Apollo Server
+title: Implementing a Subgraph with Apollo Server
---
This article demonstrates how to create a **subgraph** for a federated supergraph using Node.js and Apollo Server.
diff --git a/docs/source/using-federation/gateway-performance.mdx b/docs/source/using-federation/gateway-performance.mdx
new file mode 100644
index 00000000000..085412dda1d
--- /dev/null
+++ b/docs/source/using-federation/gateway-performance.mdx
@@ -0,0 +1,111 @@
+---
+title: Improving Gateway Performance
+subtitle: Learn to adjust tracing, instrument middleware and plugins, and more
+description: Recommendations for improving your gateway's performance when using Apollo Server with the @apollo/gateway library.
+published: 2022-07-28
+id: TN0009
+redirectFrom:
+ - /technotes/TN0009-gateway-performance/
+---
+
+This article provides recommendations for improving your performance if your're using Apollo Server with the [`@apollo/gateway` library](./apollo-gateway-setup).
+
+For the highest performance gains, Apollo recommends migrating from `@apollo/gateway` to the GraphOS Router.
+The GraphOS Router is a high-throughput, low-latency GraphQL Federation gateway written in Rust. Its performance and consistency significantly exceed any Node.js-based gateway. See the [migration guide](/graphos/reference/migration/from-gateway).
+
+## Disable or reduce `ftv1` inline tracing
+
+Inline tracing (also known as federated tracing or `ftv1`) provides helpful field-level latency information in GraphOS Studio, however it comes at a cost: trace information can be expensive to calculate, and it's attached to subgraph responses, increasing payload size.
+
+In Apollo Server 3.6 and later, you can set the `fieldLevelInstrumentation` option to turn off inline tracing entirely, or limit tracing to a representative sample of all requests.
+
+- During load testing, we recommend disabling tracing entirely.
+- For regular production traffic, we recommend setting a low sample rate such as `0.01` (one percent of requests).
+
+[Usage Reporting plugin docs for `fieldLevelInstrumentation`](/apollo-server/api/plugin/usage-reporting#fieldlevelinstrumentation)
+
+## Change the default `maxSockets` setting
+
+The `maxSockets` setting controls the maximum number of connections that `@apollo/gateway`'s `fetch` implementation can create to each subgraph host and port. With higher values, fewer subgraph requests are queued in the gateway, but the event loop might become overloaded serializing responses from subgraphs.
+
+In `@apollo/gateway` versions prior to v0.51.0, the default `maxSockets` setting is `15`, which is too low for many systems. In later versions, the default is `Infinity`, which lends itself to the overload scenario.
+
+The following `ApolloGateway` constructor sets `maxSockets` to 50:
+
+```js
+import {ApolloGateway, RemoteGraphQLDataSource} from '@apollo/gateway';
+import fetcher from 'make-fetch-happen';
+
+const gateway = new ApolloGateway({
+ buildService({name, url}) {
+ return new RemoteGraphQLDataSource({
+ name,
+ url,
+ fetcher: fetcher.defaults({maxSockets: 50})
+ });
+ }
+});
+```
+
+[Configuring the subgraph fetcher](/apollo-server/using-federation/api/apollo-gateway/#configuring-the-subgraph-fetcher)
+
+## Instrument Gateway middleware and plugins
+
+If you've installed middleware (such as Express middleware) or Apollo Server plugins, it's worth using a code profiling tool such as [Clinic.js](https://clinicjs.org/) to investigate potential issues, such as synchronous code blocking the main thread or expensive plugin functions.
+
+## Use OpenTelemetry tracing
+
+OpenTelemetry is the Cloud Native Computing Foundation (CNCF) standard for instrumenting distributed systems. By tracing `@apollo/gateway`, subgraph services, data sources, and any other systems in the request path, you might discover that the cause of performance issues occurs outside of `@apollo/gateway`.
+
+[OpenTelemetry in `@apollo/gateway`](/federation/opentelemetry)
+
+## Investigate subgraph latency
+
+Try running load tests against the subgraphs directly. You can simulate requests from the Gateway by querying the `_entities` field:
+
+```graphql
+query MyQuery__subgraphA__0($representations: [_Any!]!) {
+ _entities(representations: $representations) {
+ ... on EntityA {
+ fieldA
+ fieldB
+ }
+ ... on EntityB {
+ fieldC
+ fieldD
+ }
+ }
+}
+```
+
+By testing `_entities` queries, you might discover that you need to implement a [DataLoader](https://github.com/graphql/dataloader) in your [reference resolvers](/federation/entities#2-define-a-reference-resolver).
+
+The slower your subgraphs, the more time the Gateway spends keeping track of concurrent in-flight requests. The Gateway's maximum requests per second drops linearly as subgraph latencies rise.
+
+## Tweak CPU and memory limits
+
+You might need to set higher CPU and memory limits on your `@apollo/gateway` pods. Determining the best limits for your system depends on a number of factors:
+
+- Size of operations
+- Cardinality of operations (number of unique shapes)
+- Complexity of query plans
+- Subgraph latency
+- Use of shared caches
+
+In general, look at increasing memory limits as Node.js is single-threaded and cannot use more than one CPU. That being said, we recommend keeping CPU utilization below 50%. At higher CPU utilization percentages, you may start to see event loop delays increase relative. Monitoring both memory usage and CPU usage metrics can help provide a clearer image of bottlenecks beyond just code profiling alone.
+
+If CPU throttling becomes a problem, consider removing the limits on your gateway pods as discussed in [this blog post on Kubernetes resource limits](https://erickhun.com/posts/kubernetes-faster-services-no-cpu-limits/).
+
+## Check query plans
+
+Query plans (the steps the Gateway takes to resolve an operation from multiple subgraphs) are almost always reasonable approximations of the original operation. They're also highly cacheable so they don't incur much of a performance penalty. But it's worth looking at them to make sure they're of an appropriate size and complexity. Fragment and abstract type usage may cause undesirable query plans in specific cases.
+
+```js
+const gateway = new ApolloGateway({
+ debug: true // print query plans to stdout
+});
+```
+
+## Add more instances
+
+`@apollo/gateway` is designed to scale horizontally. If you've tried the previous strategies and performance still isn't where it should be, distribute the load across more instances of the gateway.
diff --git a/docs/source/workflow/build-run-queries.mdx b/docs/source/workflow/build-run-queries.mdx
index 7024e9f05a8..44dfc43d203 100644
--- a/docs/source/workflow/build-run-queries.mdx
+++ b/docs/source/workflow/build-run-queries.mdx
@@ -1,5 +1,5 @@
---
-title: Build and run queries against Apollo Server
+title: Build and Run Queries Against Apollo Server
---
In non-production environments, Apollo Server 4's landing page is an embedded version of [Apollo Sandbox](/graphos/explorer/sandbox) (served at `http://localhost:4000` by default):
diff --git a/docs/source/workflow/generate-types.mdx b/docs/source/workflow/generate-types.mdx
index 18fc22fba8c..577d8ca4f14 100644
--- a/docs/source/workflow/generate-types.mdx
+++ b/docs/source/workflow/generate-types.mdx
@@ -1,5 +1,5 @@
---
-title: Generating types from a GraphQL schema
+title: Generating Types from a GraphQL Schema
description: How to ensure your resolvers are type safe
---
diff --git a/docs/source/workflow/requests.md b/docs/source/workflow/requests.md
index f06096eff46..0c9dc16b52b 100644
--- a/docs/source/workflow/requests.md
+++ b/docs/source/workflow/requests.md
@@ -1,5 +1,5 @@
---
-title: Operation request format
+title: Operation Request Format
description: How to send requests to Apollo Server over HTTP
---