Skip to content

Improve projection and serialization performance in router-runtime#2151

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/improve-projection-serialization-performance
Draft

Improve projection and serialization performance in router-runtime#2151
Copilot wants to merge 2 commits intomainfrom
copilot/improve-projection-serialization-performance

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 23, 2026

GraphQL response projection was building intermediate JS objects on every request by traversing the schema and selection set at runtime. Serialization then repeated the work via JSON.stringify. This replaces both with a single pre-compiled, plan-based stringification pass.

New: packages/router-runtime/src/stringify/

  • consts.ts — Pre-computed JSON delimiter strings (avoids repeated allocation).
  • data.tsstringifyWithoutSelectionSet (replaces stableStringify), stringifyString (fast ASCII path that bypasses JSON.stringify for plain strings), and projectWithPlan (buffer-write serializer driven by the compiled plan).
  • error.tsstringifyError with pre-computed JSON key fragments for GraphQLError.
  • projection-plan.ts — Compiles a ProjectionPlanField[] tree once per (schema, OperationDefinitionNode) pair and caches it in a WeakMap. Fields carry pre-escaped JSON key strings, scalar hints, enum value sets, @skip/@include variable lists, and type guards—so serialization is a straight buffer walk with no schema lookups, no mergeDeep, no intermediate objects.
  • stringify-with-document.tsstringifyExecutionResult: top-level entry point; retrieves the cached plan and serializes data + errors + extensions in one pass.

Changes to executor.ts

  • Removed stableStringify, projectSelectionSet, and projectDataByOperation.
  • handleResp no longer projects data upfront; returns { data, errors, stringify } where stringify(result) performs projection + serialization together.
  • Deduplication key generation now uses stringifyWithoutSelectionSet.
// Before: allocate projected object, then JSON.stringify it
executionResult.data = projectDataByOperation(executionContext);
return executionResult;

// After: raw data + lazy stringify that does projection inline
return {
  data: executionContext.data,
  errors: executionContext.errors,
  stringify(result: ExecutionResult) {
    return stringifyExecutionResult(result, executionContext);
  },
};

Test updates

  • polling.test.ts: toEqualtoMatchObject (result now carries the stringify method).
  • useOpenTelemetry.spec.ts: HTTP status is always 200 now that the data field is unconditionally present.

Copilot AI and others added 2 commits March 23, 2026 23:04
…led plan-based stringification

Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/graphql-hive/gateway/sessions/366e876a-4994-4510-bbe1-e628c9a06de1
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.

2 participants