Skip to content

Support multiple listSize directives#8872

Merged
morriswchris merged 1 commit intodevfrom
GRAPHOS-12/cmo/multiple-list-size-directives
Feb 18, 2026
Merged

Support multiple listSize directives#8872
morriswchris merged 1 commit intodevfrom
GRAPHOS-12/cmo/multiple-list-size-directives

Conversation

@morriswchris
Copy link
Copy Markdown
Contributor

@morriswchris morriswchris commented Feb 9, 2026

This is the final change on the router in the listSize enhancements. This PR allows the listSize directive to be used multiple times per field. The router aggregates the cost (e.g. takes the max expected_size) so cost stays safe across all usages. Single-directive behavior is unchanged.

Why

  • One field, multiple usage patterns – e.g. pagination via first/last vs fetch-by-ids vs no args with a fallback size. Each pattern can have its own @listsize; cost reflects the worst case.
  • Different nested fields – One directive can size by sizedFields: ["items"], another by sizedFields: ["totalCount"]. Aggregating avoids undercounting when different selections are used.
  • Fallback + dynamic – Combine assumedSize (when no arg is provided) with slicingArguments (when the client sends a value). Cost uses the max so both cases are covered.

How (example)

products(first: Int, last: Int, ids: [ID!]): [Product!]!
  @listSize(slicingArguments: ["first", "last"], sizedFields: ["items"], requireOneSlicingArgument: false)
  @listSize(assumedSize: 20, sizedFields: ["totalCount"])

Cost is computed from all directives (e.g. max of their sizes), so limits and budgeting stay correct for every way the field is used.

A federation change will be needed to leverage this feature, which will come at a later date.


Checklist

Complete the checklist (and note appropriate exceptions) before the PR is marked ready-for-review.

  • PR description explains the motivation for the change and relevant context for reviewing
  • PR description links appropriate GitHub/Jira tickets (creating when necessary)
  • Changeset is included for user-facing changes
  • Changes are compatible1
  • Documentation2 completed
  • Performance impact assessed and acceptable
  • Metrics and logs are added3 and documented
  • Tests added and passing4
    • Unit tests
    • Integration tests
    • Manual tests, as necessary

Exceptions

A subsequent PR will contain docs, and the PR to merge the feature branch into dev will contain the changeset

Notes

Footnotes

  1. It may be appropriate to bring upcoming changes to the attention of other (impacted) groups. Please endeavour to do this before seeking PR approval. The mechanism for doing this will vary considerably, so use your judgement as to how and when to do this.

  2. Configuration is an important part of many changes. Where applicable please try to document configuration examples.

  3. A lot of (if not most) features benefit from built-in observability and debug-level logs. Please read this guidance on metrics best-practices.

  4. Tick whichever testing boxes are applicable. If you are adding Manual Tests, please document the manual testing (extensively) in the Exceptions.

@apollo-librarian
Copy link
Copy Markdown
Contributor

apollo-librarian bot commented Feb 9, 2026

✅ Docs preview has no changes

The preview was not built because there were no changes.

Build ID: 701404ba0160469d2f37c2b1
Build Logs: View logs

@github-actions

This comment has been minimized.

@morriswchris morriswchris changed the base branch from dev to GRAPHOS-4/cmo/list-size-advanced-parsing February 9, 2026 15:23
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from cb41a35 to db98ca2 Compare February 9, 2026 15:24
@morriswchris morriswchris self-assigned this Feb 9, 2026
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from db98ca2 to 1d03895 Compare February 9, 2026 15:55
Comment thread apollo-federation/src/link/cost_spec_definition.rs Outdated
Comment thread apollo-federation/src/link/cost_spec_definition.rs Outdated
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from 1d03895 to f90457e Compare February 9, 2026 20:38
@morriswchris morriswchris force-pushed the GRAPHOS-4/cmo/list-size-advanced-parsing branch from 77690d1 to ab9ef32 Compare February 10, 2026 14:42
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch 8 times, most recently from 311110b to 9eb0202 Compare February 12, 2026 15:22
Comment thread apollo-router/src/plugins/demand_control/cost_calculator/schema.rs Outdated
parsed_sized_fields: Option<Arc<SizedFields>>,
list_size_directives: Option<Vec<ListSizeDirective>>,
/// One entry per list_size_directive; parsed at schema load so invalid sizedFields fail startup.
parsed_sized_fields_per_directive: Vec<Option<Arc<SizedFields>>>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question RE having an Option - could this just be Vec<Arc> instead?

Comment thread apollo-router/src/plugins/demand_control/cost_calculator/schema.rs Outdated
Comment on lines +417 to +419
let descended = list_size_directives
.iter()
.find_map(|dir| dir.descend(f.name.as_str()))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be missing the business logic case here - but is there a situation where you'd want this to be a filter_map instead, because there are multiple descended values?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked more into this and you're right. I missed the case where we had 2 leaf nodes at the same level. filter_map is the correct approach. I've updated this section.

Comment thread apollo-federation/src/link/cost_spec_definition.rs Outdated
Comment thread apollo-federation/src/subgraph/mod.rs Outdated
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch 2 times, most recently from 1f7ac59 to 926ea73 Compare February 12, 2026 17:10

impl SizedFields {
/// Empty sized fields (no list leaves, no nested paths). Used when a directive has no sizedFields.
pub(in crate::plugins::demand_control) fn empty() -> Self {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we removed Option, this means we no longer have the option for a None set of SizedFields when parsing

@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch 8 times, most recently from 66e3178 to 1691ce2 Compare February 13, 2026 01:20
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch 7 times, most recently from 3852e89 to 2863500 Compare February 17, 2026 14:53
@carodewig carodewig self-requested a review February 17, 2026 15:08
@morriswchris morriswchris force-pushed the GRAPHOS-4/cmo/list-size-advanced-parsing branch from 0c8a717 to 2861eaf Compare February 17, 2026 15:32
@morriswchris morriswchris requested a review from a team as a code owner February 17, 2026 15:32
Base automatically changed from GRAPHOS-4/cmo/list-size-advanced-parsing to dev February 17, 2026 16:17
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from 2863500 to bdda512 Compare February 17, 2026 17:39
Copy link
Copy Markdown
Member

@dariuszkuc dariuszkuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes look fine for now but once we make the change to repeatable we'll have to clean up the API (e.g. remove list_size_directive_from_field_definition and instead update the code to always process the list)

sizedFields: [String!]
requireOneSlicingArgument: Boolean = true
) on FIELD_DEFINITION
) repeatable on FIELD_DEFINITION
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not a valid schema (as in this federation change still needs to happen) so unsure if this should be included in the PR

@morriswchris
Copy link
Copy Markdown
Contributor Author

The changes look fine for now but once we make the change to repeatable we'll have to clean up the API (e.g. remove list_size_directive_from_field_definition and instead update the code to always process the list)

Thanks for the review. I agree with the cleanup of the API, which I would slot for the next router release after the federation change.

@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch 7 times, most recently from 2d0604b to 4ac694f Compare February 17, 2026 22:35
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from 4ac694f to 921fd8b Compare February 18, 2026 14:20
Comment thread .changesets/feat_multiple_list_size_directives.md
@morriswchris morriswchris force-pushed the GRAPHOS-12/cmo/multiple-list-size-directives branch from 921fd8b to 6800e0e Compare February 18, 2026 15:17
@morriswchris morriswchris enabled auto-merge (squash) February 18, 2026 15:18
@morriswchris morriswchris merged commit 209d8a6 into dev Feb 18, 2026
14 of 15 checks passed
@morriswchris morriswchris deleted the GRAPHOS-12/cmo/multiple-list-size-directives branch February 18, 2026 15:44
@abernix abernix mentioned this pull request Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants