Repository: apollographql/apollo-server (ts)

Issue:
Errors using shared documentStore with Redis KeyvAdapter
### Issue Description

After enabling Redis **KeyvAdapter** for **documentStore** there are errors on receiving requests.

```
TypeError: Cannot read properties of undefined (reading 'body')
  File "/opt/app/node_modules/graphql/language/location.js", line 23, col 30, in getLocation
    for (const match of source.body.matchAll(LineRegExp)) {
  File "/opt/app/node_modules/graphql/error/GraphQLError.js", line 128, col 39, in <anonymous>
    (0, _location.getLocation)(loc.source, loc.start),
  File "<anonymous>", in Array.map
  File "/opt/app/node_modules/graphql/error/GraphQLError.js", line 127, col 25, in new GraphQLError
    : nodeLocations.map((loc) =>
  File "/opt/app/node_modules/graphql/error/locatedError.js", line 26, col 10, in locatedError
    return new _GraphQLError.GraphQLError(originalError.message, {
  File "/opt/app/node_modules/graphql/execution/execute.js", line 503, col 54, in <anonymous>
    const error = (0, _locatedError.locatedError)(
  File "node:internal/process/task_queues", line 95, col 5, in process.processTicksAndRejections
  File "/opt/app/node_modules/@apollo/server/dist/cjs/requestPipeline.js", line 223, col 37, in execute
    const resultOrResults = await (0, incrementalDeliveryPolyfill_js_1.executeIncrementally)({
  File "/opt/app/node_modules/@apollo/server/dist/cjs/requestPipeline.js", line 158, col 32, in processGraphQLRequest
    const fullResult = await execute(requestContext);
  File "/opt/app/node_modules/@apollo/server/dist/cjs/ApolloServer.js", line 615, col 16, in internalExecuteOperation
    return await (0, requestPipeline_js_1.processGraphQLRequest)(schemaDerivedData, server, internals, requestContext);
```

The service works in multiple instances with shared redis database.

NodeJS v18.15.0
Apollo server is running as express middleware.

Dependencies:
```
    "@apollo/server": "^4.5.0",
    "@apollo/utils.keyvadapter": "^2.0.1",
    "@graphql-tools/schema": "^9.0.17",
    "@keyv/redis": "^2.5.6",
    "compression": "^1.7.4",
    "cors": "^2.8.5",
    "express": "^4.18.2",
    "graphql": "^16.6.0",
    "graphql-import-node": "^0.0.4",
    "graphql-redis-subscriptions": "^2.4.0",
    "graphql-subscriptions": "^2.0.0",
    "graphql-ws": "^5.12.0",
    "helmet": "^6.0.1",
    "keyv": "^4.5.2",
    "ws": "^8.13.0"
```

### Link to Reproduction

n/a

### Reproduction Steps

```ts
  const app = express();
  const schema = makeExecutableSchema({
    typeDefs,
    resolvers
  });

  const httpServer = http.createServer(app);
  const wsServer = new WebSocketServer({
    server: httpServer,
    path,
  });

  const serverCleanup = useServer({
    schema,
    context: (ctx) => {
      const accessToken = ctx.connectionParams?.accessToken?.toString();
      return new Context({
        accessToken,
        cache: apolloServer.cache,
        mongoClient,
      });
    },
  }, wsServer);


  const keyvCache = new KeyvAdapter(new Keyv(REDIS_ADDRESS));
  const apolloServer = new ApolloServer<Context>({
    cache: keyvCache,
    documentStore: keyvCache,
    schema,
    plugins: [
      ...sentryUrl ? [SentryErrorHandler()] : [],
      ApolloServerPluginDrainHttpServer({httpServer}),
      {
        async serverWillStart() {
          return {
            async drainServer() {
              await serverCleanup.dispose();
            },
          };
        },
      },
    ],
  });

  await apolloServer.start();

  app.use(
    path,
    cors({
      maxAge: 84600
    }),
    helmet({
      contentSecurityPolicy: production
    }),
    compression(),
    json(),
    expressMiddleware(apolloServer, {
      context: async ({req}) => {
        const accessToken = (req.headers.authorization || '')?.split(' ').pop();
        return new Context({
          accessToken,
          cache: apolloServer.cache,
          mongoClient,
        });
      },
    }),
  );

  httpServer.listen({port}, () => {
    console.log(`Apollo Server on http://localhost:${port}${path}`);
  });
```

Pull request:
fix: updated documentstore to use schema hash
If you have multiple servers running with the same schema, you may wish to share the documentStore cache among them using something such as Redis, rather than inMemory. 

Using the schema hash this should allow for sharing of the data whilst still creating a new prefix for whenever the schema changes.

Fixes #7471

Patch:
diff --git a/.changeset/wet-berries-report.md b/.changeset/wet-berries-report.md
new file mode 100644
index 000000000..95c58203b
--- /dev/null
+++ b/.changeset/wet-berries-report.md
@@ -0,0 +1,5 @@
+---
+'@apollo/server': patch
+---
+
+Previously, when users provided their own `documentStore`, Apollo Server used a random prefix per schema in order to guarantee there was no shared state from one schema to the next. Now Apollo Server uses a hash of the schema, which enables the provided document store to be shared if you choose to do so.
diff --git a/package-lock.json b/package-lock.json
index c0909a651..74cc807d4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
         "packages/*"
       ],
       "devDependencies": {
-        "@apollo/client": "3.7.10",
+        "@apollo/client": "3.7.11",
         "@apollo/gateway": "2.4.0",
         "@apollo/server-plugin-landing-page-graphql-playground": "4.0.0",
         "@apollo/subgraph": "2.4.0",
@@ -33,8 +33,8 @@
         "@types/lodash.sumby": "4.6.7",
         "@types/lodash.xorby": "4.7.7",
         "@types/negotiator": "0.6.1",
-        "@types/node": "14.18.41",
-        "@types/node-fetch": "2.6.2",
+        "@types/node": "14.18.42",
+        "@types/node-fetch": "2.6.3",
         "@types/qs-middleware": "1.0.1",
         "@types/retry": "0.12.2",
         "@types/superagent": "4.1.16",
@@ -52,10 +52,10 @@
         "compression": "1.7.4",
         "cors": "2.8.5",
         "cspell": "6.31.1",
-        "eslint": "8.36.0",
+        "eslint": "8.37.0",
         "eslint-plugin-import": "2.27.5",
         "express": "4.18.2",
-        "glob": "9.3.2",
+        "glob": "9.3.4",
         "graphql": "16.6.0",
         "graphql-tag": "2.12.6",
         "jest": "29.5.0",
@@ -74,8 +74,8 @@
         "rollup": "3.20.2",
         "supertest": "6.3.3",
         "test-listen": "1.1.0",
-        "ts-jest": "29.0.5",
-        "typescript": "5.0.2"
+        "ts-jest": "29.1.0",
+        "typescript": "5.0.3"
       },
       "engines": {
         "node": ">=14.16.0",
@@ -97,9 +97,9 @@
       "link": true
     },
     "node_modules/@apollo/client": {
-      "version": "3.7.10",
-      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.10.tgz",
-      "integrity": "sha512-/k1MfrqPKYiPNdHcOzdxg9cEx96vhAGxAcSorzfBvV29XtFQcYW2cPNQOTjK/fpSMtqVo8UNmu5vwQAWD1gfCg==",
+      "version": "3.7.11",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.11.tgz",
+      "integrity": "sha512-uLg2KtxoAyj9ta7abLxXx8cGRM7HypCkXVmxtL7Ko//N5g37aoJ3ca7VYoFCMUFO1BXBulj+yKVl0U3+ILj5AQ==",
       "dependencies": {
         "@graphql-typed-document-node/core": "^3.1.1",
         "@wry/context": "^0.7.0",
@@ -107,7 +107,7 @@
         "@wry/trie": "^0.3.0",
         "graphql-tag": "^2.12.6",
         "hoist-non-react-statics": "^3.3.2",
-        "optimism": "^0.16.1",
+        "optimism": "^0.16.2",
         "prop-types": "^15.7.2",
         "response-iterator": "^0.2.6",
         "symbol-observable": "^4.0.0",
@@ -137,17 +137,6 @@
         }
       }
     },
-    "node_modules/@apollo/client/node_modules/@wry/context": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.0.tgz",
-      "integrity": "sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==",
-      "dependencies": {
-        "tslib": "^2.3.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/@apollo/composition": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/@apollo/composition/-/composition-2.4.0.tgz",
@@ -2645,14 +2634,14 @@
       }
     },
     "node_modules/@eslint/eslintrc": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
-      "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
+      "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
       "dev": true,
       "dependencies": {
         "ajv": "^6.12.4",
         "debug": "^4.3.2",
-        "espree": "^9.5.0",
+        "espree": "^9.5.1",
         "globals": "^13.19.0",
         "ignore": "^5.2.0",
         "import-fresh": "^3.2.1",
@@ -2706,9 +2695,9 @@
       }
     },
     "node_modules/@eslint/js": {
-      "version": "8.36.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
-      "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
+      "version": "8.37.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz",
+      "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -4746,13 +4735,14 @@
       "license": "MIT"
     },
     "node_modules/@types/node": {
-      "version": "14.18.41",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.41.tgz",
-      "integrity": "sha512-2cfHr8AsUjKx6u4Q+d2eqK51z8+HueoumCQGCKVt95y/yGG4uajOuCANSnE20mbLw94h3tMcddIJ8nYkTu2mFw=="
+      "version": "14.18.42",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz",
+      "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg=="
     },
     "node_modules/@types/node-fetch": {
-      "version": "2.6.2",
-      "license": "MIT",
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
+      "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
       "dependencies": {
         "@types/node": "*",
         "form-data": "^3.0.0"
@@ -5105,8 +5095,9 @@
       }
     },
     "node_modules/@wry/context": {
-      "version": "0.6.1",
-      "license": "MIT",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.0.tgz",
+      "integrity": "sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==",
       "dependencies": {
         "tslib": "^2.3.0"
       },
@@ -7331,15 +7322,15 @@
       }
     },
     "node_modules/eslint": {
-      "version": "8.36.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
-      "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
+      "version": "8.37.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz",
+      "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==",
       "dev": true,
       "dependencies": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.4.0",
-        "@eslint/eslintrc": "^2.0.1",
-        "@eslint/js": "8.36.0",
+        "@eslint/eslintrc": "^2.0.2",
+        "@eslint/js": "8.37.0",
         "@humanwhocodes/config-array": "^0.11.8",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -7350,8 +7341,8 @@
         "doctrine": "^3.0.0",
         "escape-string-regexp": "^4.0.0",
         "eslint-scope": "^7.1.1",
-        "eslint-visitor-keys": "^3.3.0",
-        "espree": "^9.5.0",
+        "eslint-visitor-keys": "^3.4.0",
+        "espree": "^9.5.1",
         "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
@@ -7516,11 +7507,15 @@
       }
     },
     "node_modules/eslint-visitor-keys": {
-      "version": "3.3.0",
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
+      "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
       "dev": true,
-      "license": "Apache-2.0",
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
       }
     },
     "node_modules/eslint/node_modules/escape-string-regexp": {
@@ -7655,14 +7650,14 @@
       }
     },
     "node_modules/espree": {
-      "version": "9.5.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
-      "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
+      "version": "9.5.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
+      "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
       "dev": true,
       "dependencies": {
         "acorn": "^8.8.0",
         "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.3.0"
+        "eslint-visitor-keys": "^3.4.0"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -8441,13 +8436,13 @@
       }
     },
     "node_modules/glob": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.2.tgz",
-      "integrity": "sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==",
+      "version": "9.3.4",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.4.tgz",
+      "integrity": "sha512-qaSc49hojMOv1EPM4EuyITjDSgSKI0rthoHnvE81tcOi1SCVndHko7auqxdQ14eiQG2NDBJBE86+2xIrbIvrbA==",
       "dev": true,
       "dependencies": {
         "fs.realpath": "^1.0.0",
-        "minimatch": "^7.4.1",
+        "minimatch": "^8.0.2",
         "minipass": "^4.2.4",
         "path-scurry": "^1.6.1"
       },
@@ -8479,15 +8474,15 @@
       }
     },
     "node_modules/glob/node_modules/minimatch": {
-      "version": "7.4.3",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz",
-      "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==",
+      "version": "8.0.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.2.tgz",
+      "integrity": "sha512-ikHGF67ODxj7vS5NKU2wvTsFLbExee+KXVCnBWh8Cg2hVJfBMQIrlo50qru/09E0EifjnU8dZhJ/iHhyXJM6Mw==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
       },
       "engines": {
-        "node": ">=10"
+        "node": ">=16 || 14 >=14.17"
       },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
@@ -11528,10 +11523,11 @@
       }
     },
     "node_modules/optimism": {
-      "version": "0.16.1",
-      "license": "MIT",
+      "version": "0.16.2",
+      "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz",
+      "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==",
       "dependencies": {
-        "@wry/context": "^0.6.0",
+        "@wry/context": "^0.7.0",
         "@wry/trie": "^0.3.0"
       }
     },
@@ -13609,9 +13605,9 @@
       }
     },
     "node_modules/ts-jest": {
-      "version": "29.0.5",
-      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
-      "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
+      "version": "29.1.0",
+      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz",
+      "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==",
       "dev": true,
       "dependencies": {
         "bs-logger": "0.x",
@@ -13634,7 +13630,7 @@
         "@jest/types": "^29.0.0",
         "babel-jest": "^29.0.0",
         "jest": "^29.0.0",
-        "typescript": ">=4.3"
+        "typescript": ">=4.3 <6"
       },
       "peerDependenciesMeta": {
         "@babel/core": {
@@ -13846,9 +13842,9 @@
       }
     },
     "node_modules/typescript": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz",
-      "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==",
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz",
+      "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==",
       "devOptional": true,
       "bin": {
         "tsc": "bin/tsc",
@@ -14617,9 +14613,9 @@
       "requires": {}
     },
     "@apollo/client": {
-      "version": "3.7.10",
-      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.10.tgz",
-      "integrity": "sha512-/k1MfrqPKYiPNdHcOzdxg9cEx96vhAGxAcSorzfBvV29XtFQcYW2cPNQOTjK/fpSMtqVo8UNmu5vwQAWD1gfCg==",
+      "version": "3.7.11",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.7.11.tgz",
+      "integrity": "sha512-uLg2KtxoAyj9ta7abLxXx8cGRM7HypCkXVmxtL7Ko//N5g37aoJ3ca7VYoFCMUFO1BXBulj+yKVl0U3+ILj5AQ==",
       "requires": {
         "@graphql-typed-document-node/core": "^3.1.1",
         "@wry/context": "^0.7.0",
@@ -14627,23 +14623,13 @@
         "@wry/trie": "^0.3.0",
         "graphql-tag": "^2.12.6",
         "hoist-non-react-statics": "^3.3.2",
-        "optimism": "^0.16.1",
+        "optimism": "^0.16.2",
         "prop-types": "^15.7.2",
         "response-iterator": "^0.2.6",
         "symbol-observable": "^4.0.0",
         "ts-invariant": "^0.10.3",
         "tslib": "^2.3.0",
         "zen-observable-ts": "^1.2.5"
-      },
-      "dependencies": {
-        "@wry/context": {
-          "version": "0.7.0",
-          "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.0.tgz",
-          "integrity": "sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==",
-          "requires": {
-            "tslib": "^2.3.0"
-          }
-        }
       }
     },
     "@apollo/composition": {
@@ -16673,14 +16659,14 @@
       "dev": true
     },
     "@eslint/eslintrc": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
-      "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz",
+      "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==",
       "dev": true,
       "requires": {
         "ajv": "^6.12.4",
         "debug": "^4.3.2",
-        "espree": "^9.5.0",
+        "espree": "^9.5.1",
         "globals": "^13.19.0",
         "ignore": "^5.2.0",
         "import-fresh": "^3.2.1",
@@ -16714,9 +16700,9 @@
       }
     },
     "@eslint/js": {
-      "version": "8.36.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
-      "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
+      "version": "8.37.0",
+      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.37.0.tgz",
+      "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==",
       "dev": true
     },
     "@graphql-codegen/cli": {
@@ -18430,12 +18416,14 @@
       "dev": true
     },
     "@types/node": {
-      "version": "14.18.41",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.41.tgz",
-      "integrity": "sha512-2cfHr8AsUjKx6u4Q+d2eqK51z8+HueoumCQGCKVt95y/yGG4uajOuCANSnE20mbLw94h3tMcddIJ8nYkTu2mFw=="
+      "version": "14.18.42",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz",
+      "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg=="
     },
     "@types/node-fetch": {
-      "version": "2.6.2",
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
+      "integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
       "requires": {
         "@types/node": "*",
         "form-data": "^3.0.0"
@@ -18684,7 +18672,9 @@
       }
     },
     "@wry/context": {
-      "version": "0.6.1",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.0.tgz",
+      "integrity": "sha512-LcDAiYWRtwAoSOArfk7cuYvFXytxfVrdX7yxoUmK7pPITLk5jYh2F8knCwS7LjgYL8u1eidPlKKV6Ikqq0ODqQ==",
       "requires": {
         "tslib": "^2.3.0"
       }
@@ -20293,15 +20283,15 @@
       "version": "1.0.5"
     },
     "eslint": {
-      "version": "8.36.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
-      "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
+      "version": "8.37.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.37.0.tgz",
+      "integrity": "sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==",
       "dev": true,
       "requires": {
         "@eslint-community/eslint-utils": "^4.2.0",
         "@eslint-community/regexpp": "^4.4.0",
-        "@eslint/eslintrc": "^2.0.1",
-        "@eslint/js": "8.36.0",
+        "@eslint/eslintrc": "^2.0.2",
+        "@eslint/js": "8.37.0",
         "@humanwhocodes/config-array": "^0.11.8",
         "@humanwhocodes/module-importer": "^1.0.1",
         "@nodelib/fs.walk": "^1.2.8",
@@ -20312,8 +20302,8 @@
         "doctrine": "^3.0.0",
         "escape-string-regexp": "^4.0.0",
         "eslint-scope": "^7.1.1",
-        "eslint-visitor-keys": "^3.3.0",
-        "espree": "^9.5.0",
+        "eslint-visitor-keys": "^3.4.0",
+        "espree": "^9.5.1",
         "esquery": "^1.4.2",
         "esutils": "^2.0.2",
         "fast-deep-equal": "^3.1.3",
@@ -20532,18 +20522,20 @@
       }
     },
     "eslint-visitor-keys": {
-      "version": "3.3.0",
+      "version": "3.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz",
+      "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==",
       "dev": true
     },
     "espree": {
-      "version": "9.5.0",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
-      "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
+      "version": "9.5.1",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz",
+      "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==",
       "dev": true,
       "requires": {
         "acorn": "^8.8.0",
         "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.3.0"
+        "eslint-visitor-keys": "^3.4.0"
       }
     },
     "esprima": {
@@ -21115,13 +21107,13 @@
       }
     },
     "glob": {
-      "version": "9.3.2",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.2.tgz",
-      "integrity": "sha512-BTv/JhKXFEHsErMte/AnfiSv8yYOLLiyH2lTg8vn02O21zWFgHPTfxtgn1QRe7NRgggUhC8hacR2Re94svHqeA==",
+      "version": "9.3.4",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.4.tgz",
+      "integrity": "sha512-qaSc49hojMOv1EPM4EuyITjDSgSKI0rthoHnvE81tcOi1SCVndHko7auqxdQ14eiQG2NDBJBE86+2xIrbIvrbA==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
-        "minimatch": "^7.4.1",
+        "minimatch": "^8.0.2",
         "minipass": "^4.2.4",
         "path-scurry": "^1.6.1"
       },
@@ -21136,9 +21128,9 @@
           }
         },
         "minimatch": {
-          "version": "7.4.3",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.3.tgz",
-          "integrity": "sha512-5UB4yYusDtkRPbRiy1cqZ1IpGNcJCGlEMG17RKzPddpyiPKoCdwohbED8g4QXT0ewCt8LTkQXuljsUfQ3FKM4A==",
+          "version": "8.0.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.2.tgz",
+          "integrity": "sha512-ikHGF67ODxj7vS5NKU2wvTsFLbExee+KXVCnBWh8Cg2hVJfBMQIrlo50qru/09E0EifjnU8dZhJ/iHhyXJM6Mw==",
           "dev": true,
           "requires": {
             "brace-expansion": "^2.0.1"
@@ -23281,9 +23273,11 @@
       }
     },
     "optimism": {
-      "version": "0.16.1",
+      "version": "0.16.2",
+      "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.16.2.tgz",
+      "integrity": "sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ==",
       "requires": {
-        "@wry/context": "^0.6.0",
+        "@wry/context": "^0.7.0",
         "@wry/trie": "^0.3.0"
       }
     },
@@ -24741,9 +24735,9 @@
       }
     },
     "ts-jest": {
-      "version": "29.0.5",
-      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
-      "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
+      "version": "29.1.0",
+      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz",
+      "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==",
       "dev": true,
       "requires": {
         "bs-logger": "0.x",
@@ -24885,9 +24879,9 @@
       }
     },
     "typescript": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz",
-      "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==",
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz",
+      "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==",
       "devOptional": true
     },
     "ua-parser-js": {
diff --git a/package.json b/package.json
index 2504b0450..b9dbe3d87 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
     "npm": ">=8.5.0"
   },
   "devDependencies": {
-    "@apollo/client": "3.7.10",
+    "@apollo/client": "3.7.11",
     "@apollo/gateway": "2.4.0",
     "@apollo/server-plugin-landing-page-graphql-playground": "4.0.0",
     "@apollo/subgraph": "2.4.0",
@@ -60,8 +60,8 @@
     "@types/lodash.sumby": "4.6.7",
     "@types/lodash.xorby": "4.7.7",
     "@types/negotiator": "0.6.1",
-    "@types/node": "14.18.41",
-    "@types/node-fetch": "2.6.2",
+    "@types/node": "14.18.42",
+    "@types/node-fetch": "2.6.3",
     "@types/qs-middleware": "1.0.1",
     "@types/retry": "0.12.2",
     "@types/superagent": "4.1.16",
@@ -79,10 +79,10 @@
     "compression": "1.7.4",
     "cors": "2.8.5",
     "cspell": "6.31.1",
-    "eslint": "8.36.0",
+    "eslint": "8.37.0",
     "eslint-plugin-import": "2.27.5",
     "express": "4.18.2",
-    "glob": "9.3.2",
+    "glob": "9.3.4",
     "graphql": "16.6.0",
     "graphql-tag": "2.12.6",
     "jest": "29.5.0",
@@ -101,8 +101,8 @@
     "rollup": "3.20.2",
     "supertest": "6.3.3",
     "test-listen": "1.1.0",
-    "ts-jest": "29.0.5",
-    "typescript": "5.0.2"
+    "ts-jest": "29.1.0",
+    "typescript": "5.0.3"
   },
   "jest": {
     "projects": [
@@ -111,6 +111,6 @@
   },
   "volta": {
     "node": "18.15.0",
-    "npm": "9.6.2"
+    "npm": "9.6.3"
   }
 }
diff --git a/packages/server/src/ApolloServer.ts b/packages/server/src/ApolloServer.ts
index 68a5ac369..75086d959 100644
--- a/packages/server/src/ApolloServer.ts
+++ b/packages/server/src/ApolloServer.ts
@@ -11,6 +11,7 @@ import {
   type GraphQLSchema,
   type ParseOptions,
   print,
+  printSchema,
   type TypedQueryDocumentNode,
   type ValidationContext,
   type ValidationRule,
@@ -22,7 +23,6 @@ import {
 } from '@apollo/utils.keyvaluecache';
 import loglevel from 'loglevel';
 import Negotiator from 'negotiator';
-import * as uuid from 'uuid';
 import { newCachePolicy } from './cachePolicy.js';
 import { determineApolloConfig } from './determineApolloConfig.js';
 import {
@@ -63,6 +63,7 @@ import { newHTTPGraphQLHead, prettyJSONStringify } from './runHttpQuery.js';
 import { SchemaManager } from './utils/schemaManager.js';
 import { isDefined } from './utils/isDefined.js';
 import { UnreachableCaseError } from './utils/UnreachableCaseError.js';
+import { computeCoreSchemaHash } from './utils/computeCoreSchemaHash.js';
 import type { WithRequired } from '@apollo/utils.withrequired';
 import type { ApolloServerOptionsWithStaticSchema } from './externalTypes/constructor.js';
 import type { GatewayExecutor } from '@apollo/server-gateway-interface';
@@ -728,13 +729,15 @@ export class ApolloServer<in out TContext extends BaseContext = BaseContext> {
       // same DocumentStore for different schemas because that might make us
       // treat invalid operations as valid. If we're using the default
       // DocumentStore, then we just create it from scratch each time we get a
-      // new schema. If we're using a user-provided DocumentStore, then we use a
-      // random prefix each time we get a new schema.
+      // new schema. If we're using a user-provided DocumentStore, then we use
+      // the schema hash as a prefix.
       documentStore:
         providedDocumentStore === undefined
           ? new InMemoryLRUCache<DocumentNode>()
           : providedDocumentStore,
-      documentStoreKeyPrefix: providedDocumentStore ? `${uuid.v4()}:` : '',
+      documentStoreKeyPrefix: providedDocumentStore
+        ? `${computeCoreSchemaHash(printSchema(schema))}:`
+        : '',
     };
   }
 


Test patch:
diff --git a/packages/server/src/__tests__/documentStore.test.ts b/packages/server/src/__tests__/documentStore.test.ts
index 9f78158c5..f9c7cc9ee 100644
--- a/packages/server/src/__tests__/documentStore.test.ts
+++ b/packages/server/src/__tests__/documentStore.test.ts
@@ -4,6 +4,9 @@ import gql from 'graphql-tag';
 import { InMemoryLRUCache } from '@apollo/utils.keyvaluecache';
 import { ApolloServer } from '..';
 import { jest, describe, it, expect } from '@jest/globals';
+import { makeExecutableSchema } from '@graphql-tools/schema';
+import { printSchema } from 'graphql/index';
+import { computeCoreSchemaHash } from '../utils/computeCoreSchemaHash';
 
 const typeDefs = gql`
   type Query {
@@ -81,11 +84,16 @@ describe('ApolloServer documentStore', () => {
     const keys = documentStore.keys();
     expect(keys).toHaveLength(1);
     const theKey = keys[0];
-    const [uuid, hash] = theKey.split(':');
-    expect(typeof uuid).toBe('string');
-    expect(hash).toEqual(operations.simple.hash);
 
-    const result = await documentStore.get(`${uuid}:${hash}`);
+    const schema = makeExecutableSchema({ typeDefs, resolvers });
+    const expectedSchemaHash = computeCoreSchemaHash(printSchema(schema));
+
+    const [schemaHash, documentHash] = theKey.split(':');
+    expect(typeof schemaHash).toBe('string');
+    expect(schemaHash).toEqual(expectedSchemaHash);
+    expect(documentHash).toEqual(operations.simple.hash);
+
+    const result = await documentStore.get(`${schemaHash}:${documentHash}`);
     expect(result).toMatchObject(documentNodeMatcher);
 
     await server.executeOperation(operations.simple.op);