Skip to content

perf(entgql): avoid COUNT(*) for pageInfo-only connection queries#625

Open
tutranngoc wants to merge 1 commit intoent:masterfrom
tutranngoc:master
Open

perf(entgql): avoid COUNT(*) for pageInfo-only connection queries#625
tutranngoc wants to merge 1 commit intoent:masterfrom
tutranngoc:master

Conversation

@tutranngoc
Copy link

@tutranngoc tutranngoc commented Jan 29, 2026

PR Description: Avoid unnecessary COUNT(*) query when resolving pageInfo

When querying a connection with pageInfo, we always execute an extra SQL query (SELECT COUNT(*)). This is not required for computing pageInfo and adds avoidable dat

The build() call in:

conn.build(nodes, pager, after, first, before, last)

already computes cursor fields (startCursor, endCursor) and correctly determines pagination flags (hasNextPage, hasPreviousPage) based on the paging arguments and returned nodes.

Currently we also derive flags using TotalCount, which forces a COUNT(*):

conn.PageInfo.HasNextPage = first != nil && conn.TotalCount > 0
conn.PageInfo.HasPreviousPage = last != nil && conn.TotalCount > 0

This makes every request that includes pageInfo pay for a COUNT(*), even when callers don’t request totalCount and we don’t actually need it.

What this PR changes:

  • Stops triggering SELECT COUNT(*) when it’s not needed for pageInfo.
  • Relies on the existing build() logic for pageInfo instead of TotalCount.

Why it matters

  • Reduces database load by removing redundant COUNT(*) queries.
  • Helps prevent query amplification in nested resolvers (a common source of N+1-like behavior).
  • Improves latency for list queries that request pageInfo but not totalCount.

Example query affected:

variants(first: $firstVariant, after: $afterVariant) {
    edges {
      cursor
      node {
        id
        title
        barcode
        baseID
        costPrice
        height
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
image

@tutranngoc tutranngoc changed the title entgql: update pagination logic to check only totalCountField for edges handling perf(entgql): avoid COUNT(*) for pageInfo-only connection queries Jan 29, 2026
@tutranngoc
Copy link
Author

@a8m @giautm Please check this pull request for me 🙇‍♂️🙇‍♂️🙇‍♂️

@giautm
Copy link
Collaborator

giautm commented Jan 29, 2026

@tutranngoc fyi, you can use entcache package to cache query result of count(). So it wont hit database twice.

https://github.com/ariga/entcache

@tutranngoc
Copy link
Author

@tutranngoc fyi, you can use entcache package to cache query result of count(). So it wont hit database twice.

https://github.com/ariga/entcache

@giautm Thank you for sharing, however, my preference is to eliminate the need for a select count when using pageInfo, even during the first query. Querying for count when using pageInfo is unnecessary.

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