apollographql / apollographql/federation
Redundant queries (similar to N+1) if same type is present in multiple places
- Dominant language
- TypeScript
- Stars
- 725
- Forks
- 276
- Avg merge
- 1h 47m
- Merged PRs (30d)
- 1
Description
**Describe the bug**
If objects of the same type is present in different `paths` , multople requests are made to fetch the same resource
**To Reproduce**
Full setup here: https://github.com/ahrushetskyi/apollo_fed_np1
Subgraph A:
```graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0")
type Action @federation__key(fields: "id") {
config: ActionConfig!
defaultTemplate: Template!
delay: Int!
id: ID!
}
union ActionConfig = ConfigOne | ConfigThree | ConfigTwo
type ConfigOne {
id: ID!
otherTemplate: Template!
someTemplate: Template!
}
type ConfigThree {
id: ID!
wrongTemplate: Template!
}
type ConfigTwo {
id: ID!
leftTemplate: Template!
rightTemplate: Template!
}
type Query {
actions: [Action!]!
}
type Template @federation__extends @federation__key(fields: "id") {
id: ID!
}
```
Subgraph B
```graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0")
type Template @federation__key(fields: "id") {
body: String!
id: ID!
name: String!
}
```
Query:
```graphql
query ExampleQuery {
actions {
config {
... on ConfigOne {
id
otherTemplate {
name
body
id
}
someTemplate {
name
body
id
}
}
... on ConfigThree {
id
wrongTemplate {
name
body
id
}
}
... on ConfigTwo {
id
leftTemplate {
name
body
id
}
rightTemplate {
name
body
id
}
}
}
}
}
```
Query plan
```graphql
QueryPlan {
Sequence {
Fetch(service: "schemaA") {
{
actions {
config {
__typename
... on ConfigOne {
id
otherTemplate {
__typename
id
}
someTemplate {
__typename
id
}
}
... on ConfigThree {
id
wrongTemplate {
__typename
id
}
}
... on ConfigTwo {
id
leftTemplate {
__typename
id
}
rightTemplate {
__typename
id
}
}
}
}
}
},
Parallel {
Flatten(path: "actions.@.config.otherTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.someTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.wrongTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.leftTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.rightTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
},
},
}
```

**Expected behavior**
It should not perform 5 queries to fetch `Template`s. It is possible to do that in one query
**Versions:**
`rover -V`: Rover 0.9.0
`./router -V`: 1.0.0
Contributor guide
Research direction
Start with the linked reproduction repository and inspect the generated QueryPlan for the federated query shown here, focusing on the five parallel fetches to schemaB. Compare the plan with the expected behavior in the issue; done means the reproduction no longer performs five separate Template fetches.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100