# What is the best strategy for conditionally removing a field in a Federated GraphQL setup

**URL:** <https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078>\
**Category:** Schema Design\
**Created:** [May 19, 2025, 3:07pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078 "2025-05-19T15:07:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ya-at](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/ya-at/32/6101_2.png) [@ya-at](https://community.apollographql.com/u/ya-at)\
**Post date:** [May 19, 2025, 3:07pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/1 "2025-05-19T15:07:47Z")

</div>

Hello everyone,

I’m working with two federated subgraphs:  
• Subgraph A defines an entity `EntityA`.  
• Subgraph B defines an entity `EntityB`.

In subgraph A, `EntityA` references `EntityB` through a field `field1: EntityB`. In subgraph B, `EntityB` has a field `field2: Int`.

The challenge: subgraph A has logic to determine whether `field2` should be removed for a specific `EntityB`, but `field2` is defined in subgraph B.

I’ve considered several approaches, but each feels problematic:

1. Adding a flag (e.g., `removeField2`) to `@key()` on `EntityB` so the entity resolver can omit `field2`. The downside is that all other subgraphs need to know about `removeField2` (since key should be the same).
2. Adding an `EntityA` resolver in subgraph B that uses an `removeField2 @external` flag. However, this forces subgraph B to be aware of subgraph A’s existence, which breaks the intended separation.
3. Creating an additional subgraph that somehow manages the logic between subgraph A and subgraph B — though I’m unsure how best to do that.

I also attempted using the `@provides` directive, but that’s static. I need a scenario where, if `removeField2` is true (known by subgraph A), we omit the field, while otherwise letting subgraph B resolve it.

Has anyone dealt with a similar “conditional field removal” scenario in a federated setup? Any best practices or patterns you could suggest?

Thanks in advance for your ideas!

---

<div class="post-metadata">

**Author:** ![dkuc](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/dkuc/32/2892_2.png) [@dkuc](https://community.apollographql.com/u/dkuc)\
**Post date:** [May 19, 2025, 10:16pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/2 "2025-05-19T22:16:51Z")

</div>

Hello 👋

Unsure what you mean by “removal of a field”, but if I understand correctly, `EntityA` is a parent of `EntityB` and has some logic within subgraph A (based on information on `EntityA`) that determines whether `EntityB.field2` should be `NULL` or not, i.e.

```graphql
// subgraph A
type EntityA @key(fields: "id") {
  id: ID!
  // some other fields
}

// subgraph B
type EntityA @key(fields: "id") {
  id: ID!
  field1: EntityB
}

type EntityB @key(fields: "id") {
  id: ID!
  field2: String // value based on some conditional logic
}

```

If I understand correctly, you should be able to achieve t his through `@context` ([docs](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/entities/use-contexts)), i.e.

```graphql
// subgraph B
type EntityA @key(fields: "id") @context(name: "myContext") {
  id: ID!
  field1: EntityB
  // this field would be computed in subgraphA
  shouldFieldBeNull: Boolean! @external
}

type EntityB @key(fields: "id") {
  id: ID!
  field2(overwrite: Boolean! @fromContext(field: "$myContext { shouldFieldBeNull }")): String
}

```

---

<div class="post-metadata">

**Author:** ![ya-at](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/ya-at/32/6101_2.png) [@ya-at](https://community.apollographql.com/u/ya-at)\
**Post date:** [May 20, 2025, 9:30am UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/3 "2025-05-20T09:30:42Z")

</div>

Thank you for your reply! I’m trying to understand how subgraph B references subgraph A’s internal logic. Wouldn’t this create a coupling between the two subgraphs and potentially violate the principle of separation of concerns? Or is it acceptable for subgraph B to know about subgraph A in a GraphQL federation context?

---

<div class="post-metadata">

**Author:** ![dkuc](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/dkuc/32/2892_2.png) [@dkuc](https://community.apollographql.com/u/dkuc)\
**Post date:** [May 20, 2025, 2:23pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/4 "2025-05-20T14:23:56Z")

</div>

Per your problem description, in order to resolve `EntityB.field2` you do need some information from subgraph A so there is no way around it. Regardless whether it is across subgraphs or within the same graph, your `EntityB` needs input from the parent `EntityA`.

---

<div class="post-metadata">

**Author:** ![ya-at](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/ya-at/32/6101_2.png) [@ya-at](https://community.apollographql.com/u/ya-at)\
**Post date:** [May 20, 2025, 2:41pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/5 "2025-05-20T14:41:29Z")

</div>

Yes, I see your point. Another option might be to add a `shouldFieldBeNull` flag directly to `EntityB` and include it as part of `EntityB`’s key. That way, subgraph B wouldn’t need to know anything about subgraph A. With this approach, any subgraph could decide to remove the field if necessary—although most likely they won’t need to.

However, this solution is also problematic because it forces every subgraph that references `EntityB` to handle the `shouldFieldBeNull` field, even though it’s optional. This can create unnecessary complexity in subgraphs that don’t need this logic.

---

<div class="post-metadata">

**Author:** ![dkuc](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/dkuc/32/2892_2.png) [@dkuc](https://community.apollographql.com/u/dkuc)\
**Post date:** [May 20, 2025, 3:16pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/6 "2025-05-20T15:16:18Z")

</div>

I’d argue that adding unnecessary elements to the `@key` field set is an anti pattern. `@key` should specify all the necessary information to uniquely identify the entity.

We recommend using `@requires` (information from same entity but other subgraph) and/or `@context` (ancestor information) directives to propagate additional information to the specific resolvers.

---

<div class="post-metadata">

**Author:** ![ya-at](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/ya-at/32/6101_2.png) [@ya-at](https://community.apollographql.com/u/ya-at)\
**Post date:** [May 20, 2025, 3:49pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/7 "2025-05-20T15:49:36Z")

</div>

`@requires` seems promising. However, consider a scenario where subgraph C also references `EntityB` but has no need to remove any fields. For instance, if we do something like:

```graphql
// subgraph A
type EntityA @key(fields: "id") {
  id: ID!
  field1: EntityB
}

type EntityB @key(fields: "id") {
  id: ID!
  shouldRemoveField2: Boolean @inaccessible
}

// subgraph B
type EntityB @key(fields: "id") {
  id: ID!
  shouldRemoveField2: Boolean @external
  field2: Int @requires(fields: "shouldRemoveField2")
}

// subgraph C
type Query {
  someC: EntityC
}

type EntityC @key(fields: "id") {
  id: ID!
  field1: EntityB
}

type EntityB @key(fields: "id") {
  id: ID!
}

```

It becomes impossible to execute the query `{ someC { field1 { field2 } }}`, because subgraph B requires `shouldRemoveField2`, while subgraph C does not provide it.

A possible workaround is present in your first answer:

```graphql
// subgraph A
type Query {
  myA: EntityA
}
type EntityA @key(fields: "id") {
  id: ID!
  shouldRemoveField2: Boolean @inaccessible
  field1: EntityB @shareable
}

type EntityB @key(fields: "id", resolvable: false) {
  id: ID!
}

// subgraph B
type EntityA @key(fields: "id") {
  id: ID!
  shouldRemoveField2: Boolean @external
  field1: EntityB @requires(fields: "shouldRemoveField2") @shareable
}

type EntityB @key(fields: "id") {
  id: ID!
  field2: Int
}

```

Here, I’m unsure of the query plan for `{ myA { field1 { field2 } }}`. Will the router call the entity resolver for `EntityB`, or will it call the resolver for `EntityA` to fetch `field2`?

---

<div class="post-metadata">

**Author:** ![ya-at](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/ya-at/32/6101_2.png) [@ya-at](https://community.apollographql.com/u/ya-at)\
**Post date:** [May 20, 2025, 4:02pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/8 "2025-05-20T16:02:18Z")

</div>

The last code snippet can be improved by introducing an `entityBKey` field:

```graphql
// subgraph A
type Query {
  myA: EntityA
}

type EntityA @key(fields: "id") {
  id: ID!
  entityBKey: EntityBKey @inaccessible
}

type EntityBKey @inaccessible {
  id: ID!
  shouldRemoveField2: Boolean
}

// subgraph B
type EntityA @key(fields: "id") {
  id: ID!
  entityBKey: EntityBKey @external
  field1: EntityB @requires(fields: "id shouldRemoveField2")
}

type EntityBKey @external {
  id: ID!
  shouldRemoveField2: Boolean
}

type EntityB @key(fields: "id") {
  id: ID!
  field2: Int
}

```

This approach works, but if `entityB` were a union, using `@requires` in this way could become quite cumbersome.

---

<div class="post-metadata">

**Author:** ![dkuc](https://sea1.discourse-cdn.com/flex019/user_avatar/community.apollographql.com/dkuc/32/2892_2.png) [@dkuc](https://community.apollographql.com/u/dkuc)\
**Post date:** [May 22, 2025, 9:09pm UTC](https://community.apollographql.com/t/what-is-the-best-strategy-for-conditionally-removing-a-field-in-a-federated-graphql-setup/9078/9 "2025-05-22T21:09:31Z")

</div>

Query planner will “jump” to other subgraphs through `_entities` call to get additional entity fields.

Given your above examples 1, 2 and 3

#1 This works as long as the `shouldRemoveField2` is resolvable based on `EntityB` information only in subgraph A (its computed without any knowledge about its parent),

i.e. given your query `someC { field1 { field2 }}`, generated query plan will be

```auto
fetch(C) { someC { field1 { id } } } 
  -> fetch(A) { _entities { ... on EntityB { shouldRemoveField2 }
    -> fetch(B) { _entities { ... on EntityB { field2 } }

```

#2 and #3 will not work as you cannot have only one subgraph specifying requirement on the shareable field. Even if you remove the `EntityA.field1` from `subgraphA` this still is problematic as your requirement is on specific field resolution path (i.e. it assumes that you would “enter” `EntityB` through that `EntityA.field1` field on `subgraphB` … but if you add another subgraph where you extend `EntityB` it may jump there through `_entities` query.
