Repository: newrelic/newrelic-node-apollo-server-plugin
Pull request #114 (2021-07-14 14:08:03)

removed pinning versioned tests to <3.0.0
## Details
When I did https://github.com/newrelic/newrelic-node-apollo-server-plugin/pull/106 I started branch before we pinned the tests to `<3.0.0` and never rebased to fix.  Locally I was testing on all versioned but I guess in CI when it merged main it was still pinned.  This removes the pinning for realz



Patch:
diff --git a/README.md b/README.md
index f1cfe33..ff53aa8 100644
--- a/README.md
+++ b/README.md
@@ -171,7 +171,7 @@ query {
 }
 ```
 
-`post /query/<anonymous>/libraries.books`
+`post /query/<anonymous>/libraries.books.author.name`
 
 For more information on how transactions are named, including how query errors may impact naming, please see the [transaction documentation](./docs/transactions.md).
 
@@ -183,9 +183,9 @@ Two new metrics have been introduced to understand the behavior of your GraphQL
 
 #### Operation Metrics
 
-`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-unique-path]`
+`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-path]`
 
-Operation metrics are very similar to how transaction names are constructed including the operation type, operation name and deepest unique path. These metrics represent the durations of the individual queries or mutations and can be used to compare outside of the context of individual transactions which may have multiple queries.
+Operation metrics are very similar to how transaction names are constructed including the operation type, operation name and deepest-path. These metrics represent the durations of the individual queries or mutations and can be used to compare outside of the context of individual transactions which may have multiple queries.
 
 If you would like to have a list of the top 10 slowest operations, the following query can be used to pull the data on demand or as a part of a dashboard. The 'Bar' chart type is a recommended visualization for this query.
 
@@ -216,11 +216,11 @@ Segments and spans (when Distributed Tracing enabled) are captured for GraphQL o
 
 #### Operation Segments/Spans
 
-`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-unique-path]`
+`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-path]`
 
-Operation segments/spans include the operation type, operation name and deepest unique path. These represent the individual duration and attributes of a specific invocation within a transaction or trace.
+Operation segments/spans include the operation type, operation name and deepest-path. These represent the individual duration and attributes of a specific invocation within a transaction or trace.
 
-The operation type and operation name are captured as attributes on a segment or span as well as the query with obfuscated arguments.
+The operation type, operation name and deepest-path are captured as attributes on a segment or span as well as the query with obfuscated arguments.
 
 For more information on collected attributes, see the [segments and spans documentation](./docs/segments-and-spans.md)
 
diff --git a/docs/metrics.md b/docs/metrics.md
index 81a4e33..d0c30a2 100644
--- a/docs/metrics.md
+++ b/docs/metrics.md
@@ -6,7 +6,7 @@ For more information on querying metrics and creating charts, see the [Resources
 
 ## Operation Metrics
 
-`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-unique-path]`
+`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-path]`
 
 Operation metrics include the operation type, operation name and deepest-path. These metrics represent the durations of the individual queries or mutations and can be used to compare outside of the context of individual transactions which may have multiple queries.
 
@@ -14,7 +14,7 @@ Operation metrics include the operation type, operation name and deepest-path. T
 
 **Operation Name:** The operation name when provided or `<anonymous>`.
 
-**Deepest Unique Path:** The deepest path included in the selection set of a query where only one field was selected at each level. Since operation names may be reused, this helps further determine uniqueness of a given operation. See the description on the [transactions](./transactions.md#deepest-unique-path) page for more details.
+**Deepest Path:** The deepest path resolved (or attempted in the case of a validation error). Since operation names may be reused, this helps further determine uniqueness of a given operation.
 
 ## Field Resolve Metrics
 
diff --git a/docs/segments-and-spans.md b/docs/segments-and-spans.md
index 9ad82ba..24263ad 100644
--- a/docs/segments-and-spans.md
+++ b/docs/segments-and-spans.md
@@ -4,11 +4,9 @@ Segments and spans (when Distributed Tracing enabled) are captured for GraphQL o
 
 ## Operation Segments/Spans
 
-`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-unique-path]`
+`/GraphQL/operation/ApolloServer/[operation-type]/[operation-name]/[deepest-path]`
 
-Operation segments/spans include the operation type, operation name and deepest unique path. These represent the individual duration and attributes of a specific invocation within a transaction or trace.
-
-For more details on the parts, see the [transactions](./transactions.md#details) page.
+Operation segments/spans include the operation type, operation name and deepest-path. These represent the individual duration and attributes of a specific invocation within a transaction or trace.
 
 **Attributes**
 
@@ -16,6 +14,7 @@ For more details on the parts, see the [transactions](./transactions.md#details)
 | ---------------------- | ---------------- | -------- |
 | graphql.operation.type | query or mutation| included |
 | graphql.operation.name | Name given to the operation or anonymous | included |
+| graphql.operation.deepestPath | Deepest path resolved as the part of an operation | included |
 | graphql.operation.query | The original GraphQL query with arguments obfuscated | included |
 
 To exclude capture of the query attribute (or any attribute), the attribute name will need to be added to the 'attributes' exclude list or segment/span attributes exclude lists individually.
diff --git a/docs/transactions.md b/docs/transactions.md
index 2a723e1..73addcd 100644
--- a/docs/transactions.md
+++ b/docs/transactions.md
@@ -13,7 +13,7 @@ query {
 }
 ```
 
-`post /query/<anonymous>/libraries.books`
+`post /query/<anonymous>/libraries.books.author.name`
 
 ---
 
@@ -21,88 +21,21 @@ Transactions are captured as web transactions, associated with the underlying fr
 
 We leverage several details in a transaction name to attempt to mostly group unique query representations: http method, operation type, operation name and the deepest path resolved (the first, if multiple).
 
-The raw representation of a transaction looks like the following: `/WebTransaction/{framework-name}/POST//{operation-type}/{operation-name}/{deepest-unique-path}`
+The raw representation of a transaction looks like the following: `/WebTransaction/{framework-name}/POST//{operation-type}/{operation-name}/{deepest-path}`
 
-For an Express usage of Apollo Server, that may look like: `/WebTransaction/Expressjs/POST//query/<anonymous>/libraries.books`
+For an Express usage of Apollo Server, that may look like: `/WebTransaction/Expressjs/POST//query/<anonymous>/libraries.books.author.name`
 
-The transaction on New Relic One will ultimately display similar to: `post /query/<anonymous>/libraries.books`.
+The transaction on New Relic One will ultimately display similar to: `post /query/<anonymous>/libraries.books.author.name`.
 
 ## Details
 
-### Http Method
+**Http Method:** Http method/verb for the web request. Data may be requested via GET or POST and is surfaced to differentiate similar to other web transactions.
 
-Http method/verb for the web request. Data may be requested via GET or POST and is surfaced to differentiate similar to other web transactions.
+**Operation Type:** Indicates if the operation was a query or a mutation.
 
-### Operation Type
+**Operation Name:** The operation name when provided or `<anonymous>`.
 
-Indicates if the operation was a query or a mutation.
-
-### Operation Name
-
-The operation name when provided or `<anonymous>`.
-
-`query { libraries }` would use the operation name '<anonymous>' because a name was not provided.
-
-A named query such as `query GetLibraries { libraries }` would use the operation name `GetLibraries'.
-
-### Deepest Unique Path
-
-The deepest path included in the selection set of a query where only one field was selected at each level. Since operation names may be reused, this helps further determine uniqueness of a given operation.
-
-We use the deepest unique path (instead of deepest path like prior) to avoid making arbitrary decision in naming, which may imply/hide details of what could cause slowness for an application.
-
-For the query:
-
-```
-query {
-  libraries {
-    branch
-    booksInStock {
-      isbn,
-      title,
-      author
-    }
-    magazinesInStock {
-      issue,
-      title
-    }
-  }
-}
-```
-
-We will select a deepest unique path of 'libraries' as we select multiple fields beyond that point. Any resolver executed beyond that point may contribute to the performance characteristics of the transaction.
-
-If the query were to only select one field per resolver, we select the full path as each selection set is unique.
-
-The query:
-
-```
-query {
-  libraries {
-    booksInStock {
-      title
-    }
-  }
-}
-```
-
-Will result in the deepest unique path: 'libraries.booksInStock.title'.
-
-`id` and `__typename` fields are automatically excluded from the naming decision.
-
-For example, a federated sub graph query:
-
-```
-query {
-  libraries {
-    branch
-    __typename
-    id
-  }
-}
-```
-
-Would result in the deepest unique path of: 'libraries.branch'.
+**Deepest Path:** The deepest path resolved (or attempted in the case of a validation error). Since operation names may be reused, this helps further determine uniqueness of a given operation.
 
 ## Naming on Error
 
@@ -120,6 +53,7 @@ Below is an example of querying for a field that does not exist (`doesnotexist`)
 query GetBooksByLibrary {
   libraries {
     books {
+      title
       doesnotexist {
         name
       }
@@ -157,7 +91,7 @@ In these situations, the `query` attribute on the operation span associated with
 
 Apollo Server allows the sending of batch queries. In these situations, there are multiple operation/queries in play to impact naming.
 
-To continue to best uniquely identify transaction groupings, we aggregate the operation names after an additional `/batch` indicator. These names are likely to be quite long. We are considering dropping the deepest unique path from these names but are currently maintaining consistency.
+To continue to best uniquely identify transaction groupings, we aggregate the operation names after an additional `/batch` indicator. These names are likely to be quite long. We are considering dropping the deepest-path from these names but are currently maintaining consistency.
 
 Below is an example of a batch query and what that may look like in NR One.
 
@@ -183,6 +117,6 @@ Below is an example of a batch query and what that may look like in NR One.
 ]
 ```
 
-`post /batch/query/GetBookForLibrary/library.books/mutation/<anonymous>/addThing`
+`post /batch/query/GetBookForLibrary/library.books.author.name/mutation/<anonymous>/addThing`
 
-Here you see `batch/` followed by `query/GetBookForLibrary/library.books` and `mutation/<anonymous>/addThing`.
+Here you see `batch/` followed by `query/GetBookForLibrary/library.books.author.name` and `mutation/<anonymous>/addThing`.
\ No newline at end of file
diff --git a/lib/create-plugin.js b/lib/create-plugin.js
index dd1dae4..4ec28d1 100644
--- a/lib/create-plugin.js
+++ b/lib/create-plugin.js
@@ -27,11 +27,9 @@ const FIELD_PATH_ATTR = 'graphql.field.path'
 const FIELD_ARGS_ATTR = 'graphql.field.args'
 const OPERATION_TYPE_ATTR = 'graphql.operation.type'
 const OPERATION_NAME_ATTR = 'graphql.operation.name'
+const OPERATION_PATH_ATTR = 'graphql.operation.deepestPath'
 const OPERATION_QUERY_ATTR = 'graphql.operation.query'
-
 const INTROSPECTION_TYPES = ['__schema', '__type']
-const IGNORED_PATH_FIELDS = ['id', '__typename']
-
 const DESTINATIONS = {
   NONE: 0x00
 }
@@ -216,7 +214,7 @@ function createPlugin(instrumentationApi, config = {}) {
           const operationDetails = getOperationDetails(responseContext)
 
           if (operationDetails) {
-            const {operationName, operationType, deepestUniquePath} = operationDetails
+            const {operationName, operationType, deepestPath} = operationDetails
 
             operationSegment.addAttribute(OPERATION_TYPE_ATTR, operationType)
 
@@ -228,8 +226,10 @@ function createPlugin(instrumentationApi, config = {}) {
             let formattedOperation = `${operationType}/${formattedName}`
 
             // Certain requests, such as introspection, won't hit any resolvers
-            if (deepestUniquePath) {
-              formattedOperation += `/${deepestUniquePath}`
+            if (deepestPath) {
+              operationSegment.addAttribute(OPERATION_PATH_ATTR, deepestPath)
+
+              formattedOperation += `/${deepestPath}`
             }
 
             segmentName = formattedOperation
@@ -289,14 +289,13 @@ function isTopLevelField(fieldInfo) {
 function getDetailsFromDocument(document) {
   const [ definition ] = document.definitions
 
-  const deepestUniquePath = getDeepestUniqueSelection(definition)
-
+  const deepestSelectionPath = getDeepestSelectionPath(definition)
   const definitionName = definition.name && definition.name.value
 
   return {
     operationType: definition.operation,
     operationName: definitionName,
-    deepestUniquePath: deepestUniquePath.join('.')
+    deepestPath: deepestSelectionPath.join('.')
   }
 }
 
@@ -341,37 +340,39 @@ function setTransactionName(transaction, transactionName) {
 }
 
 /**
- * Returns the deepest path in the document definition selectionSet
- * where only one field was selected.
- *
- * 'id' and '__typename' fields are filtered out of consideration to improve
- * naming in sub graph scenarioes.
+ * Returns the deepest path as an array of parts
+ * from an apollo-server document definition.
  */
-function getDeepestUniqueSelection(definition) {
-  const deepestPath = []
-  let selection = definition
-  while (selection.selectionSet) {
-    const filtered = selection.selectionSet.selections.filter((currentSelection) => {
-      // Inline fragments describe the prior element (_entities) but contain
-      // selections for further naming.
-      if (currentSelection.kind === 'InlineFragment') {
-        return true
-      }
-
-      return IGNORED_PATH_FIELDS.indexOf(currentSelection.name.value) < 0
-    })
+function getDeepestSelectionPath(definition) {
+  let deepestPath = null
 
-    if (filtered.length > 1) {
-      break // selections not unique
-    }
+  definition.selectionSet.selections.forEach((selection) => {
+    searchSelection(selection)
+  })
 
-    selection = filtered[0]
+  return deepestPath
 
-    // Inline fragments do not have a name.
-    selection.name && deepestPath.push(selection.name.value)
+  /**
+   * Search each selection path until no-more sub-selections
+   * exist. If the curent path is deeper than deepestPath,
+   * deepestPath is replaced.
+   */
+  function searchSelection(selection, currentParts) {
+    const parts = currentParts ? [...currentParts] : []
+
+    // we have found that when queries contain InlineFragments
+    // they lack `name` property, check for property before adding to parts
+    // see https://github.com/newrelic/newrelic-node-apollo-server-plugin/issues/84
+    selection.name && parts.push(selection.name.value)
+
+    if (selection.selectionSet) {
+      selection.selectionSet.selections.forEach((innerSelection) => {
+        searchSelection(innerSelection, parts)
+      })
+    } else if (!deepestPath || parts.length > deepestPath.length) {
+      deepestPath = parts
+    }
   }
-
-  return deepestPath
 }
 
 function recordResolveSegment(segment, scope) {


Test patch:
diff --git a/tests/integration/config-capture-scalars.test.js b/tests/integration/config-capture-scalars.test.js
index e99b25b..855cc93 100644
--- a/tests/integration/config-capture-scalars.test.js
+++ b/tests/integration/config-capture-scalars.test.js
@@ -57,10 +57,10 @@ function createNoScalarTests(t) {
       }
     }`
 
-    const path = 'library'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [
@@ -132,10 +132,10 @@ function createScalarTests(t) {
       }
     }`
 
-    const path = 'library'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [
@@ -190,3 +190,4 @@ function createScalarTests(t) {
     })
   })
 }
+
diff --git a/tests/integration/metrics.test.js b/tests/integration/metrics.test.js
index e2794d1..c9dd59c 100644
--- a/tests/integration/metrics.test.js
+++ b/tests/integration/metrics.test.js
@@ -83,10 +83,10 @@ function createMetricsTests(t) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', () => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
 
       t.metrics([
         `${OPERATION_PREFIX}/${operationPart}`,
@@ -121,12 +121,12 @@ function createMetricsTests(t) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', () => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
 
       const operationMetrics1 = [
@@ -154,7 +154,7 @@ function createMetricsTests(t) {
     const { helper, serverUrl } = t.context
 
     const query = '{ libraries { books { title author { name } } } }'
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
     const querySha = crypto.createHash('sha256').update(query).digest('hex')
     const withQuery = `${serverUrl}?extensions={"persistedQuery":{"version":1,
       "sha256Hash":"${querySha}"}}&query=${query}`
@@ -162,7 +162,7 @@ function createMetricsTests(t) {
       "sha256Hash":"${querySha}"}}`
 
     helper.agent.on('transactionFinished', () => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
 
       t.metrics([
         `${OPERATION_PREFIX}/${operationPart}`,
diff --git a/tests/versioned/apollo-federation/package.json b/tests/versioned/apollo-federation/package.json
index 5e8cab3..fdc54e8 100644
--- a/tests/versioned/apollo-federation/package.json
+++ b/tests/versioned/apollo-federation/package.json
@@ -10,12 +10,10 @@
       "dependencies": {
         "@apollo/federation": ">=0.25.2",
         "@apollo/gateway": ">=0.25.2 <0.31.0",
-        "apollo-server": ">=2.25.1 <3.0.0"
+        "apollo-server": ">=2.25.1"
       },
       "files": [
-        "segments.test.js",
-        "transaction-naming.test.js",
-        "sub-graph-transactions.test.js"
+        "segments.test.js"
       ]
     },
     {
@@ -29,9 +27,7 @@
         "apollo-server": "2.25.1"
       },
       "files": [
-        "segments.test.js",
-        "transaction-naming.test.js",
-        "sub-graph-transactions.test.js"
+        "segments.test.js"
       ]
     }
   ],
diff --git a/tests/versioned/apollo-federation/segments.test.js b/tests/versioned/apollo-federation/segments.test.js
index 394df2d..3729eca 100644
--- a/tests/versioned/apollo-federation/segments.test.js
+++ b/tests/versioned/apollo-federation/segments.test.js
@@ -55,7 +55,7 @@ function createFederatedSegmentsTests(t, frameworkName) {
       const bookExternal = formatExternalSegment(t.context.bookUrl)
       const magazineExternal = formatExternalSegment(t.context.magazineUrl)
 
-      const operationPart = `query/${ANON_PLACEHOLDER}/libraries`
+      const operationPart = `query/${ANON_PLACEHOLDER}/libraries.booksInStock.isbn`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -91,6 +91,7 @@ function createFederatedSegmentsTests(t, frameworkName) {
     const booksQueryName = 'GetBooksForLibraries'
     const booksQuery = `query ${booksQueryName} {
       libraries {
+        branch
         booksInStock {
           isbn,
           title,
@@ -102,6 +103,7 @@ function createFederatedSegmentsTests(t, frameworkName) {
     const magazineQueryName = 'GetMagazinesForLibraries'
     const magazineQuery = `query ${magazineQueryName} {
       libraries {
+        branch
         magazinesInStock {
           issue,
           title
@@ -120,9 +122,9 @@ function createFederatedSegmentsTests(t, frameworkName) {
         return
       }
 
-      const operationPart1 = `query/${booksQueryName}/libraries.booksInStock`
+      const operationPart1 = `query/${booksQueryName}/libraries.booksInStock.isbn`
       const expectedQuery1Name = `${operationPart1}`
-      const operationPart2 = `query/${magazineQueryName}/libraries.magazinesInStock`
+      const operationPart2 = `query/${magazineQueryName}/libraries.magazinesInStock.issue`
       const expectedQuery2Name = `${operationPart2}`
 
       const batchTransactionPrefix = `${TRANSACTION_PREFIX}//batch`
diff --git a/tests/versioned/apollo-federation/sub-graph-transactions.test.js b/tests/versioned/apollo-federation/transaction-inline-fragments.test.js
similarity index 60%
rename from tests/versioned/apollo-federation/sub-graph-transactions.test.js
rename to tests/versioned/apollo-federation/transaction-inline-fragments.test.js
index 849abe2..b8fa33c 100644
--- a/tests/versioned/apollo-federation/sub-graph-transactions.test.js
+++ b/tests/versioned/apollo-federation/transaction-inline-fragments.test.js
@@ -11,7 +11,7 @@ const { setupFederatedGatewayServerTests } = require('./federated-gateway-server
 const { checkResult } = require('../common')
 
 setupFederatedGatewayServerTests({
-  suiteName: 'sub graph transaction naming',
+  suiteName: 'query with inline fragments',
   createTests: createFederatedSegmentsTests,
   instrumentSubGraphs: true
 })
@@ -23,7 +23,7 @@ setupFederatedGatewayServerTests({
  * @param {*} t a tap test instance
  */
 function createFederatedSegmentsTests(t) {
-  t.test('should properly name when inline fragments exist', (t) => {
+  t.test('should nest sub graphs under operation', (t) => {
     const { helper, serverUrl } = t.context
 
     /**
@@ -48,10 +48,10 @@ function createFederatedSegmentsTests(t) {
      *   }
      * }`
      * The ones with `...on Library` are [InlineFragments](https://graphql.org/learn/queries/#inline-fragments)
-     * which lack name properites on all the selections within document.
-     * Without the fix in https://github.com/newrelic/newrelic-node-apollo-server-plugin/pull/100
+     * which lack name properites on all the selections within document
+     * without the fix in https://github.com/newrelic/newrelic-node-apollo-server-plugin/pull/100
      * they would crash and not properly name the transactions, also the query request
-     * would fail.
+     * would fail
      */
     const query = `query SubGraphs {
       libraries {
@@ -71,9 +71,9 @@ function createFederatedSegmentsTests(t) {
     let transactions = []
     const expectedTransactions = [
       'WebTransaction/Expressjs/POST//query/<anonymous>/libraries.branch',
-      'WebTransaction/Expressjs/POST//query/<anonymous>/_entities.booksInStock',
-      'WebTransaction/Expressjs/POST//query/<anonymous>/_entities.magazinesInStock',
-      'WebTransaction/Expressjs/POST//query/SubGraphs/libraries'
+      'WebTransaction/Expressjs/POST//query/<anonymous>/_entities.booksInStock.isbn',
+      'WebTransaction/Expressjs/POST//query/<anonymous>/_entities.magazinesInStock.issue',
+      'WebTransaction/Expressjs/POST//query/SubGraphs/libraries.booksInStock.isbn'
     ]
 
     helper.agent.on('transactionFinished', (transaction) => {
@@ -82,60 +82,7 @@ function createFederatedSegmentsTests(t) {
 
     executeQuery(serverUrl, query, (err, result) => {
       t.equal(transactions.length, 4, 'should create 4 transactions')
-
-      t.same(transactions, expectedTransactions, 'should properly name each transaction')
-      t.error(err)
-      checkResult(t, result, () => {
-        t.end()
-      })
-    })
-  })
-
-  t.test('should filter id and __typename fields from unique naming', (t) => {
-    const { helper, serverUrl } = t.context
-
-    /**
-     * The 'libraries' sub graph service gets queried as:
-     * query {
-     *   libraries {
-     *     branch
-     *     __typename
-     *     id
-     *   }
-     * }
-     *
-     * 'id' and '__typename' should get filtered out for a
-     * specific name of 'libraries.branch'.
-     */
-    const query = `query SubGraphs {
-      libraries {
-        branch
-        booksInStock {
-          isbn,
-          title,
-          author
-        }
-        magazinesInStock {
-          issue,
-          title
-        }
-      }
-    }`
-
-    let transactions = []
-    const expectedPath = 'libraries.branch'
-    const expectedTransaction
-      = `WebTransaction/Expressjs/POST//query/<anonymous>/${expectedPath}`
-
-    helper.agent.on('transactionFinished', (transaction) => {
-      transactions.push(transaction.name)
-    })
-
-    executeQuery(serverUrl, query, (err, result) => {
-      const hasTransaction = transactions.indexOf(expectedTransaction) >= 0
-
-      t.ok(hasTransaction, `should have a transaction named: '${expectedTransaction}'`)
-
+      t.same(expectedTransactions, transactions, 'should properly name each transaction')
       t.error(err)
       checkResult(t, result, () => {
         t.end()
diff --git a/tests/versioned/apollo-federation/transaction-naming.test.js b/tests/versioned/apollo-federation/transaction-naming.test.js
index 95aa6fa..9ae01d0 100644
--- a/tests/versioned/apollo-federation/transaction-naming.test.js
+++ b/tests/versioned/apollo-federation/transaction-naming.test.js
@@ -26,7 +26,7 @@ setupFederatedGatewayServerTests({
 function createFederatedTransactionNamingTests(t, frameworkName) {
   const TRANSACTION_PREFIX = `WebTransaction/${frameworkName}/POST`
 
-  t.test('anonymous query, multi selections should return deepest unique path', (t) => {
+  t.test('should properly name transaction when an anonymous federated query', (t) => {
     const { helper, serverUrl } = t.context
 
     const query = `query {
@@ -49,8 +49,9 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
         return
       }
 
-      const operationPart = `query/${ANON_PLACEHOLDER}/libraries`
-      t.equal(transaction.name, `${TRANSACTION_PREFIX}//${operationPart}`)
+      const operationPart = `query/${ANON_PLACEHOLDER}/libraries.booksInStock.isbn`
+      t.equal(transaction.name,
+      `${TRANSACTION_PREFIX}//${operationPart}`)
     })
 
     executeQuery(serverUrl, query, (err, result) => {
@@ -61,35 +62,7 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
     })
   })
 
-  t.test('anonymous query, single selections should return deepest unique path', (t) => {
-    const { helper, serverUrl } = t.context
-
-    const query = `query {
-      libraries {
-        booksInStock {
-          title
-        }
-      }
-    }`
-
-    helper.agent.on('transactionFinished', (transaction) => {
-      if (shouldSkipTransaction(transaction)) {
-        return
-      }
-
-      const operationPart = `query/${ANON_PLACEHOLDER}/libraries.booksInStock.title`
-      t.equal(transaction.name, `${TRANSACTION_PREFIX}//${operationPart}`)
-    })
-
-    executeQuery(serverUrl, query, (err, result) => {
-      t.error(err)
-      checkResult(t, result, () => {
-        t.end()
-      })
-    })
-  })
-
-  t.test('named query, multi selections should return deepest unique path', (t) => {
+  t.test('should properly name transaction when a named, federated query', (t) => {
     const { helper, serverUrl } = t.context
 
     const query = `query booksInStock {
@@ -102,41 +75,14 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
       }
     }`
 
-    helper.agent.on('transactionFinished', (transaction) => {
-      if (shouldSkipTransaction(transaction)) {
-        return
-      }
-
-      const operationPart = 'query/booksInStock/libraries'
-      t.equal(transaction.name, `${TRANSACTION_PREFIX}//${operationPart}`)
-    })
-
-    executeQuery(serverUrl, query, (err, result) => {
-      t.error(err)
-      checkResult(t, result, () => {
-        t.end()
-      })
-    })
-  })
-
-  t.test('named query, single selections should return deepest unique path', (t) => {
-    const { helper, serverUrl } = t.context
-
-    const query = `query booksInStock {
-      libraries {
-        booksInStock {
-          title
-        }
-      }
-    }`
-
     helper.agent.on('transactionFinished', (transaction) => {
       if (shouldSkipTransaction(transaction)) {
         return
       }
 
       const operationPart = 'query/booksInStock/libraries.booksInStock.title'
-      t.equal(transaction.name, `${TRANSACTION_PREFIX}//${operationPart}`)
+      t.equal(transaction.name,
+      `${TRANSACTION_PREFIX}//${operationPart}`)
     })
 
     executeQuery(serverUrl, query, (err, result) => {
@@ -153,6 +99,7 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
     const booksQueryName = 'GetBooksForLibraries'
     const booksQuery = `query ${booksQueryName} {
       libraries {
+        branch
         booksInStock {
           isbn,
           title,
@@ -164,6 +111,7 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
     const magazineQueryName = 'GetMagazinesForLibraries'
     const magazineQuery = `query ${magazineQueryName} {
       libraries {
+        branch
         magazinesInStock {
           issue,
           title
@@ -177,13 +125,12 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
       if (shouldSkipTransaction(transaction)) {
         return
       }
-      const operationPart1 = `query/${booksQueryName}/libraries.booksInStock`
-      const operationPart2 = `query/${magazineQueryName}/libraries.magazinesInStock`
+      const operationPart1 = `query/${booksQueryName}/libraries.booksInStock.isbn`
+      const operationPart2 = `query/${magazineQueryName}/libraries.magazinesInStock.issue`
 
       const batchTransactionPrefix = `${TRANSACTION_PREFIX}//batch`
 
-      t.equal(
-        transaction.name,
+      t.equal(transaction.name,
         `${batchTransactionPrefix}/${operationPart1}/${operationPart2}`
       )
     })
@@ -198,3 +145,4 @@ function createFederatedTransactionNamingTests(t, frameworkName) {
     })
   })
 }
+
diff --git a/tests/versioned/apollo-server-express/package.json b/tests/versioned/apollo-server-express/package.json
index 8251fb7..2c9394f 100644
--- a/tests/versioned/apollo-server-express/package.json
+++ b/tests/versioned/apollo-server-express/package.json
@@ -8,7 +8,7 @@
         "node": ">=12"
       },
       "dependencies": {
-        "apollo-server-express": ">=2.14.0 <3.0.0",
+        "apollo-server-express": ">=2.14.0",
         "express": "4.17.1"
       },
       "files": [
diff --git a/tests/versioned/apollo-server-fastify/package.json b/tests/versioned/apollo-server-fastify/package.json
index 0cb5475..59346b9 100644
--- a/tests/versioned/apollo-server-fastify/package.json
+++ b/tests/versioned/apollo-server-fastify/package.json
@@ -8,8 +8,8 @@
         "node": ">=12"
       },
       "dependencies": {
-        "apollo-server-fastify": ">=2.14.0 <3.0.0",
-        "fastify": "3.5.0"
+        "apollo-server-fastify": ">=2.14.0",
+        "fastify": "3.17.0"
       },
       "files": [
         "segments.test.js",
diff --git a/tests/versioned/apollo-server-fastify/segments.test.js b/tests/versioned/apollo-server-fastify/segments.test.js
index 4c1b3fc..8356907 100644
--- a/tests/versioned/apollo-server-fastify/segments.test.js
+++ b/tests/versioned/apollo-server-fastify/segments.test.js
@@ -93,6 +93,7 @@ function createFastifySegmentsTests(t, frameworkName) {
     const query = `query {
       libraries {
         books {
+          title
           author {
             name
           }
@@ -100,10 +101,10 @@ function createFastifySegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.author.name'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -128,7 +129,7 @@ function createFastifySegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -143,10 +144,10 @@ function createFastifySegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -172,6 +173,48 @@ function createFastifySegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+        children: [{
+          name: `${OPERATION_PREFIX}/${operationPart}`,
+          children: [
+            { name: `${RESOLVE_PREFIX}/libraries` },
+            { name: `${RESOLVE_PREFIX}/libraries.books` },
+            { name: `${RESOLVE_PREFIX}/libraries.books.title` },
+            { name: `${RESOLVE_PREFIX}/libraries.books.isbn` }
+          ]
+        }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, serverUrl } = t.context
 
@@ -321,10 +364,10 @@ function createFastifySegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -377,12 +420,12 @@ function createFastifySegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -486,6 +529,7 @@ function createFastifySegmentsTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -493,10 +537,10 @@ function createFastifySegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -521,3 +565,4 @@ function createFastifySegmentsTests(t, frameworkName) {
     })
   })
 }
+
diff --git a/tests/versioned/apollo-server-hapi/package.json b/tests/versioned/apollo-server-hapi/package.json
index aabff65..1b912fd 100644
--- a/tests/versioned/apollo-server-hapi/package.json
+++ b/tests/versioned/apollo-server-hapi/package.json
@@ -8,7 +8,7 @@
         "node": ">=12 <16"
       },
       "dependencies": {
-        "apollo-server-hapi": ">=2.14.0 <3.0.0",
+        "apollo-server-hapi": ">=2.14.0",
         "@hapi/hapi": "18.4.1"
       },
       "files": [
diff --git a/tests/versioned/apollo-server-hapi/segments.test.js b/tests/versioned/apollo-server-hapi/segments.test.js
index 33ac248..cd75c69 100644
--- a/tests/versioned/apollo-server-hapi/segments.test.js
+++ b/tests/versioned/apollo-server-hapi/segments.test.js
@@ -99,6 +99,7 @@ function createHapiSegmentsTests(t, frameworkName) {
     const query = `query {
       libraries {
         books {
+          title
           author {
             name
           }
@@ -106,10 +107,10 @@ function createHapiSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.author.name'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -137,7 +138,7 @@ function createHapiSegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -152,10 +153,10 @@ function createHapiSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -184,6 +185,51 @@ function createHapiSegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+        children: [{
+          name: 'Nodejs/Middleware/Hapi/handler//gql',
+            children: [{
+              name: `${OPERATION_PREFIX}/${operationPart}`,
+              children: [
+                { name: `${RESOLVE_PREFIX}/libraries` },
+                { name: `${RESOLVE_PREFIX}/libraries.books` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.title` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.isbn` }
+              ]
+            }]
+        }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, serverUrl } = t.context
 
@@ -345,10 +391,10 @@ function createHapiSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -404,12 +450,12 @@ function createHapiSegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -519,6 +565,7 @@ function createHapiSegmentsTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -526,10 +573,10 @@ function createHapiSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -557,3 +604,4 @@ function createHapiSegmentsTests(t, frameworkName) {
     })
   })
 }
+
diff --git a/tests/versioned/apollo-server-koa/package.json b/tests/versioned/apollo-server-koa/package.json
index 1980a93..ae50b1d 100644
--- a/tests/versioned/apollo-server-koa/package.json
+++ b/tests/versioned/apollo-server-koa/package.json
@@ -8,7 +8,7 @@
         "node": ">=12"
       },
       "dependencies": {
-        "apollo-server-koa": ">=2.14.0 <3.0.0",
+        "apollo-server-koa": ">=2.14.0",
         "koa": ">=2.13.0"
       },
       "files": [
diff --git a/tests/versioned/apollo-server-koa/segments.test.js b/tests/versioned/apollo-server-koa/segments.test.js
index 8ddf56b..33ce99f 100644
--- a/tests/versioned/apollo-server-koa/segments.test.js
+++ b/tests/versioned/apollo-server-koa/segments.test.js
@@ -99,6 +99,7 @@ function createKoaSegmentsTests(t, frameworkName) {
     const query = `query {
       libraries {
         books {
+          title
           author {
             name
           }
@@ -106,10 +107,10 @@ function createKoaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.author.name'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -137,7 +138,7 @@ function createKoaSegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -152,10 +153,10 @@ function createKoaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -184,6 +185,51 @@ function createKoaSegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+        children: [{
+          name: 'Nodejs/Middleware/Koa',
+            children: [{
+              name: `${OPERATION_PREFIX}/${operationPart}`,
+              children: [
+                { name: `${RESOLVE_PREFIX}/libraries` },
+                { name: `${RESOLVE_PREFIX}/libraries.books` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.title` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.isbn` }
+              ]
+            }]
+        }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, serverUrl } = t.context
 
@@ -345,10 +391,10 @@ function createKoaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -404,12 +450,12 @@ function createKoaSegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -519,6 +565,7 @@ function createKoaSegmentsTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -526,10 +573,10 @@ function createKoaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
diff --git a/tests/versioned/apollo-server-lambda/attributes-tests.js b/tests/versioned/apollo-server-lambda/attributes-tests.js
index 1d8897b..811268d 100644
--- a/tests/versioned/apollo-server-lambda/attributes-tests.js
+++ b/tests/versioned/apollo-server-lambda/attributes-tests.js
@@ -40,7 +40,8 @@ function createAttributesTests(t) {
       const operationSegment = findSegmentByName(transaction.trace.root, operationName)
 
       const expectedOperationAttributes = {
-        'graphql.operation.type': 'query'
+        'graphql.operation.type': 'query',
+        'graphql.operation.deepestPath': 'hello'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -93,7 +94,8 @@ function createAttributesTests(t) {
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'query',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': 'hello'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -129,7 +131,7 @@ function createAttributesTests(t) {
     })
   })
 
-  t.test('named query, multi-level, should capture deepest unique path', (t) => {
+  t.test('named query, multi-level, should capture deepest path', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -144,15 +146,16 @@ function createAttributesTests(t) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationName = `${OPERATION_PREFIX}/query/${expectedName}/${path}`
+      const operationName = `${OPERATION_PREFIX}/query/${expectedName}/${deepestPath}`
       const operationSegment = findSegmentByName(transaction.trace.root, operationName)
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'query',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': deepestPath
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -219,7 +222,8 @@ function createAttributesTests(t) {
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'mutation',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': 'addThing'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
diff --git a/tests/versioned/apollo-server-lambda/errors-tests.js b/tests/versioned/apollo-server-lambda/errors-tests.js
index c600e85..15b9319 100644
--- a/tests/versioned/apollo-server-lambda/errors-tests.js
+++ b/tests/versioned/apollo-server-lambda/errors-tests.js
@@ -79,6 +79,7 @@ function createErrorTests(t) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
diff --git a/tests/versioned/apollo-server-lambda/package.json b/tests/versioned/apollo-server-lambda/package.json
index b960d16..ddee94e 100644
--- a/tests/versioned/apollo-server-lambda/package.json
+++ b/tests/versioned/apollo-server-lambda/package.json
@@ -8,7 +8,7 @@
         "node": ">=12"
       },
       "dependencies": {
-        "apollo-server-lambda": ">=2.14.0 <3.0.0"
+        "apollo-server-lambda": ">=2.14.0"
       },
       "files": [
         "segments.test.js",
diff --git a/tests/versioned/apollo-server-lambda/segments.test.js b/tests/versioned/apollo-server-lambda/segments.test.js
index 94fb059..f2371e5 100644
--- a/tests/versioned/apollo-server-lambda/segments.test.js
+++ b/tests/versioned/apollo-server-lambda/segments.test.js
@@ -98,6 +98,7 @@ function createLambdaSegmentsTests(t, frameworkName) {
     const query = `query {
       libraries {
         books {
+          title
           author {
             name
           }
@@ -105,10 +106,10 @@ function createLambdaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.author.name'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -134,7 +135,7 @@ function createLambdaSegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -149,10 +150,10 @@ function createLambdaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -179,6 +180,49 @@ function createLambdaSegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, patchedHandler, stubContext, modVersion } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+          children: [{
+            name: `${OPERATION_PREFIX}/${operationPart}`,
+            children: [
+              { name: `${RESOLVE_PREFIX}/libraries` },
+              { name: `${RESOLVE_PREFIX}/libraries.books` },
+              { name: `${RESOLVE_PREFIX}/libraries.books.title` },
+              { name: `${RESOLVE_PREFIX}/libraries.books.isbn` }
+            ]
+          }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQueryAssertResult({
+      handler: patchedHandler,
+      query,
+      context: stubContext,
+      t,
+      modVersion
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
@@ -332,10 +376,10 @@ function createLambdaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -389,12 +433,12 @@ function createLambdaSegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -493,6 +537,7 @@ function createLambdaSegmentsTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -500,10 +545,10 @@ function createLambdaSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -524,3 +569,4 @@ function createLambdaSegmentsTests(t, frameworkName) {
     })
   })
 }
+
diff --git a/tests/versioned/apollo-server-lambda/transaction-naming-tests.js b/tests/versioned/apollo-server-lambda/transaction-naming-tests.js
index 9c33daf..09b2fa8 100644
--- a/tests/versioned/apollo-server-lambda/transaction-naming-tests.js
+++ b/tests/versioned/apollo-server-lambda/transaction-naming-tests.js
@@ -73,7 +73,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('anonymous query, multi-level should return deepest unique path', (t) => {
+  t.test('anonymous query, multi-level should return deepest path', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
     const query = `query {
@@ -87,12 +87,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${path}`
+        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${deepestPath}`
       )
     })
 
@@ -105,7 +105,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -120,12 +120,44 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
+      )
+    })
+
+    executeQueryAssertResult({
+      handler: patchedHandler,
+      query,
+      context: stubContext,
+      modVersion,
+      t
+    })
+  })
+
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, patchedHandler, stubContext, modVersion } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      t.equal(
+        transaction.name,
+        `${EXPECTED_PREFIX}//query/${expectedName}/${firstDeepestPath}`
       )
     })
 
@@ -232,7 +264,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, with params, should return deepest unique path', (t) => {
+  t.test('named query, with params, should return deepest path', (t) => {
     const { helper, patchedHandler, stubContext, modVersion } = t.context
 
     const expectedName = 'GetBookForLibrary'
@@ -247,12 +279,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
       )
     })
 
@@ -284,12 +316,12 @@ function createTransactionTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path = 'library.books'
+    const DeepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const expectedQuery1Name = `query/${expectedName1}/${path}`
+      const expectedQuery1Name = `query/${expectedName1}/${DeepestPath1}`
       const expectedQuery2Name = `mutation/${ANON_PLACEHOLDER}/addThing`
       t.equal(
         transaction.name,
@@ -348,6 +380,7 @@ function createTransactionTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -355,12 +388,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${path}`
+        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${deepestPath}`
       )
     })
 
@@ -383,6 +416,7 @@ function createTransactionTests(t, frameworkName) {
     const invalidQuery = `query ${expectedName} {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -390,12 +424,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
       )
     })
 
@@ -409,3 +443,4 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 }
+
diff --git a/tests/versioned/apollo-server/package.json b/tests/versioned/apollo-server/package.json
index f3b2d60..d5857cb 100644
--- a/tests/versioned/apollo-server/package.json
+++ b/tests/versioned/apollo-server/package.json
@@ -8,7 +8,7 @@
         "node": ">=12"
       },
       "dependencies": {
-        "apollo-server": ">=2.14.0 <3.0.0"
+        "apollo-server": ">=2.14.0"
       },
       "files": [
         "transaction-naming.test.js",
diff --git a/tests/versioned/attributes-tests.js b/tests/versioned/attributes-tests.js
index daf5dd0..7e6271b 100644
--- a/tests/versioned/attributes-tests.js
+++ b/tests/versioned/attributes-tests.js
@@ -33,7 +33,8 @@ function createAttributesTests(t) {
       const operationSegment = findSegmentByName(transaction.trace.root, operationName)
 
       const expectedOperationAttributes = {
-        'graphql.operation.type': 'query'
+        'graphql.operation.type': 'query',
+        'graphql.operation.deepestPath': 'hello'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -83,7 +84,8 @@ function createAttributesTests(t) {
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'query',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': 'hello'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -116,7 +118,7 @@ function createAttributesTests(t) {
     })
   })
 
-  t.test('named query, multi-level, should capture deepest unique path', (t) => {
+  t.test('named query, multi-level, should capture deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -131,7 +133,7 @@ function createAttributesTests(t) {
       }
     }`
 
-    const deepestPath = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       const operationName = `${OPERATION_PREFIX}/query/${expectedName}/${deepestPath}`
@@ -139,7 +141,8 @@ function createAttributesTests(t) {
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'query',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': deepestPath
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
@@ -203,7 +206,8 @@ function createAttributesTests(t) {
 
       const expectedOperationAttributes = {
         'graphql.operation.type': 'mutation',
-        'graphql.operation.name': expectedName
+        'graphql.operation.name': expectedName,
+        'graphql.operation.deepestPath': 'addThing'
       }
 
       const operationAttributes = operationSegment.attributes.get(SEGMENT_DESTINATION)
diff --git a/tests/versioned/errors-tests.js b/tests/versioned/errors-tests.js
index 33dc452..179686c 100644
--- a/tests/versioned/errors-tests.js
+++ b/tests/versioned/errors-tests.js
@@ -84,6 +84,7 @@ function createErrorTests(t) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
diff --git a/tests/versioned/express-segments-default-tests.js b/tests/versioned/express-segments-default-tests.js
index 5419208..0e3a5d0 100644
--- a/tests/versioned/express-segments-default-tests.js
+++ b/tests/versioned/express-segments-default-tests.js
@@ -102,6 +102,7 @@ function createSegmentsTests(t, frameworkName) {
     const query = `query {
       libraries {
         books {
+          title
           author {
             name
           }
@@ -109,10 +110,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.author.name'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -142,7 +143,7 @@ function createSegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -157,10 +158,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -190,6 +191,52 @@ function createSegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+        children: [{
+          name: 'Expressjs/Router: /',
+          children: [{
+            name: 'Nodejs/Middleware/Expressjs/<anonymous>',
+            children: [{
+              name: `${OPERATION_PREFIX}/${operationPart}`,
+              children: [
+                { name: `${RESOLVE_PREFIX}/libraries` },
+                { name: `${RESOLVE_PREFIX}/libraries.books` }
+              ]
+            }]
+          }]
+        }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, serverUrl } = t.context
 
@@ -355,6 +402,7 @@ function createSegmentsTests(t, frameworkName) {
     const query = `query ${expectedName} {
       library(branch: "downtown") {
         books {
+          title
           author {
             name
           }
@@ -362,10 +410,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books.author.name'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -422,12 +470,12 @@ function createSegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -541,6 +589,7 @@ function createSegmentsTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -548,10 +597,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
diff --git a/tests/versioned/express-segments-scalar-tests.js b/tests/versioned/express-segments-scalar-tests.js
index 6f5cfca..100a336 100644
--- a/tests/versioned/express-segments-scalar-tests.js
+++ b/tests/versioned/express-segments-scalar-tests.js
@@ -110,10 +110,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -144,7 +144,7 @@ function createSegmentsTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -159,10 +159,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -194,6 +194,54 @@ function createSegmentsTests(t, frameworkName) {
     })
   })
 
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      const operationPart = `query/${expectedName}/${firstDeepestPath}`
+      const expectedSegments = [{
+        name: `${TRANSACTION_PREFIX}//${operationPart}`,
+        children: [{
+          name: 'Expressjs/Router: /',
+          children: [{
+            name: 'Nodejs/Middleware/Expressjs/<anonymous>',
+            children: [{
+              name: `${OPERATION_PREFIX}/${operationPart}`,
+              children: [
+                { name: `${RESOLVE_PREFIX}/libraries` },
+                { name: `${RESOLVE_PREFIX}/libraries.books` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.title` },
+                { name: `${RESOLVE_PREFIX}/libraries.books.isbn` }
+              ]
+            }]
+          }]
+        }]
+      }]
+
+      t.segments(transaction.trace.root, expectedSegments)
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
   t.test('anonymous mutation, single level', (t) => {
     const { helper, serverUrl } = t.context
 
@@ -367,10 +415,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${expectedName}/${path}`
+      const operationPart = `query/${expectedName}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
@@ -429,12 +477,12 @@ function createSegmentsTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const deepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart1 = `query/${expectedName1}/${path1}`
+      const operationPart1 = `query/${expectedName1}/${deepestPath1}`
       const expectedQuery1Name = `${operationPart1}`
       const operationPart2 = `mutation/${ANON_PLACEHOLDER}/addThing`
       const expectedQuery2Name = `${operationPart2}`
@@ -558,10 +606,10 @@ function createSegmentsTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const operationPart = `query/${ANON_PLACEHOLDER}/${path}`
+      const operationPart = `query/${ANON_PLACEHOLDER}/${deepestPath}`
       const expectedSegments = [{
         name: `${TRANSACTION_PREFIX}//${operationPart}`,
         children: [{
diff --git a/tests/versioned/transaction-naming-tests.js b/tests/versioned/transaction-naming-tests.js
index 1c94336..11317b6 100644
--- a/tests/versioned/transaction-naming-tests.js
+++ b/tests/versioned/transaction-naming-tests.js
@@ -64,7 +64,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('anonymous query, multi-level should return deepest unique path', (t) => {
+  t.test('anonymous query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const query = `query {
@@ -78,12 +78,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${path}`
+        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${deepestPath}`
       )
     })
 
@@ -95,7 +95,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, multi-level should return deepest unique path', (t) => {
+  t.test('named query, multi-level should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBooksByLibrary'
@@ -110,12 +110,43 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books'
+    const deepestPath = 'libraries.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
+      )
+    })
+
+    executeQuery(serverUrl, query, (err, result) => {
+      t.error(err)
+      checkResult(t, result, () => {
+        t.end()
+      })
+    })
+  })
+
+  t.test('named query, multi-level, should choose *first* deepest-path', (t) => {
+    const { helper, serverUrl } = t.context
+
+    const expectedName = 'GetBooksByLibrary'
+    const query = `query ${expectedName} {
+      libraries {
+        books {
+          title
+          isbn
+        }
+      }
+    }`
+
+    // .isbn is the same length but title will be first so that path should be used
+    const firstDeepestPath = 'libraries.books.title'
+
+    helper.agent.on('transactionFinished', (transaction) => {
+      t.equal(
+        transaction.name,
+        `${EXPECTED_PREFIX}//query/${expectedName}/${firstDeepestPath}`
       )
     })
 
@@ -217,7 +248,7 @@ function createTransactionTests(t, frameworkName) {
     })
   })
 
-  t.test('named query, with params, should return deepest unique path', (t) => {
+  t.test('named query, with params, should return deepest path', (t) => {
     const { helper, serverUrl } = t.context
 
     const expectedName = 'GetBookForLibrary'
@@ -232,12 +263,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'library.books'
+    const deepestPath = 'library.books.author.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
       )
     })
 
@@ -268,12 +299,12 @@ function createTransactionTests(t, frameworkName) {
       addThing(name: "added thing!")
     }`
 
-    const path1 = 'library.books'
+    const DeepestPath1 = 'library.books.author.name'
 
     const queries = [query1, query2]
 
     helper.agent.on('transactionFinished', (transaction) => {
-      const expectedQuery1Name = `query/${expectedName1}/${path1}`
+      const expectedQuery1Name = `query/${expectedName1}/${DeepestPath1}`
       const expectedQuery2Name = `mutation/${ANON_PLACEHOLDER}/addThing`
       t.equal(
         transaction.name,
@@ -332,6 +363,7 @@ function createTransactionTests(t, frameworkName) {
     const invalidQuery = `query {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -339,12 +371,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${path}`
+        `${EXPECTED_PREFIX}//query/${ANON_PLACEHOLDER}/${deepestPath}`
       )
     })
 
@@ -371,6 +403,7 @@ function createTransactionTests(t, frameworkName) {
     const invalidQuery = `query ${expectedName} {
       libraries {
         books {
+          title
           doesnotexist {
             name
           }
@@ -378,12 +411,12 @@ function createTransactionTests(t, frameworkName) {
       }
     }`
 
-    const path = 'libraries.books.doesnotexist.name'
+    const deepestPath = 'libraries.books.doesnotexist.name'
 
     helper.agent.on('transactionFinished', (transaction) => {
       t.equal(
         transaction.name,
-        `${EXPECTED_PREFIX}//query/${expectedName}/${path}`
+        `${EXPECTED_PREFIX}//query/${expectedName}/${deepestPath}`
       )
     })