Agent Wranglers

API-83Recommended

Page GraphQL lists as cursor connections

Return every list that can grow past 100 items as a connection with edges, node, cursor and pageInfo. Require a first or last argument with a cap.

How to do it

An unpaged list field lets one query fetch a million rows. graphql.org recommends cursor connections, and the Relay connection format is the common shape. Keep cursors opaque, as page lists with cursors says. Cap first the same way as cap the page size, and count it in the query cost limit.

Examples

Plain text example

type Query {
  invoices(first: Int = 20, after: String): InvoiceConnection!
}

type InvoiceConnection {
  edges: [InvoiceEdge!]!
  pageInfo: PageInfo!
}

type InvoiceEdge { cursor: String! node: Invoice! }
type PageInfo { endCursor: String hasNextPage: Boolean! }

JavaScript example

const MAX_PAGE = 100;

const invoices = async (_, { first = 20, after }, ctx) => {
  const limit = Math.min(first, MAX_PAGE);
  const rows = await ctx.db.invoicesAfter(ctx.user.id, decodeCursor(after), limit + 1);
  const edges = rows.slice(0, limit).map(node => ({ node, cursor: encodeCursor(node.id) }));
  return { edges, pageInfo: { endCursor: edges.at(-1)?.cursor ?? null, hasNextPage: rows.length > limit } };
};

Python example

MAX_PAGE = 100

def resolve_invoices(info, first: int = 20, after: str | None = None):
    limit = min(first, MAX_PAGE)
    rows = info.context.db.invoices_after(info.context.user.id, decode_cursor(after), limit + 1)
    edges = [{"node": row, "cursor": encode_cursor(row.id)} for row in rows[:limit]]
    return {"edges": edges, "page_info": {"end_cursor": edges[-1]["cursor"] if edges else None, "has_next_page": len(rows) > limit}}

How to check

Introspection on the test copy shows no list field of an object type without first or last. A query with first: 10000 returns an error or at most the capped number of items.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/api-design/graphql-and-grpc/graphql-connections">Agent Wranglers API design playbook</a>. In code you write, add a comment next to it with the same link.