Skip to content

perf: use BatchResolve queries to eliminate N+1 API calls in issue create/update #63

@iamfj

Description

@iamfj

Problem

The GraphQL layer already defines batch resolution queries:

  • BatchResolveForCreate
  • BatchResolveForUpdate
  • BatchResolveForSearch

These can resolve teams, projects, labels, milestones, and parent issues in a single GraphQL call. However, no command uses them. Instead, each resolver is called sequentially.

Current behavior

linearis issues create "title" --team Backend --assignee "Jane" --project API --labels "Bug,Critical" makes:

  1. resolveTeamId() → 1 SDK call
  2. resolveUserId() → 1-2 SDK calls
  3. resolveProjectId() → 1 SDK call
  4. resolveLabelIds() → 2 SDK calls (one per label)
  5. createIssue() → 1 GraphQL mutation

Total: 6-7 sequential API calls where 1 batch query + 1 mutation would suffice.

Expected behavior

For issues create and issues update, use the existing batch queries to resolve all entity references in a single round-trip before executing the mutation.

Design considerations

This requires a new orchestration pattern. Options:

A. Command-level batch resolution
The command collects all identifiers, calls a single batch resolver, then passes UUIDs to the service. This breaks the "resolvers handle resolution" invariant slightly but is pragmatic.

B. New batch resolver module
A batch-resolver.ts that accepts all identifiers and returns all UUIDs. Commands call this instead of individual resolvers. Maintains layer separation.

C. Keep individual resolvers, add caching
Resolvers cache responses per-request. Less change but doesn't reduce API calls.

Recommendation: Option B — aligns with existing architecture.

Scope

  • issues create — use BatchResolveForCreate
  • issues update — use BatchResolveForUpdate
  • issues list --query with filters — use BatchResolveForSearch (if advanced search is added)

Acceptance criteria

  • issues create with multiple --flags makes ≤2 API calls (1 batch resolve + 1 mutation)
  • issues update with multiple --flags makes ≤3 API calls (1 fetch context + 1 batch resolve + 1 mutation)
  • Individual resolvers still work for commands that only need one resolution
  • Unit tests for batch resolver
  • Existing tests still pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions