Paginating a list field
posts(limit: 20, offset: 40). Trivial to implement, supports 'jump to page 7' and a total count. But rows inserted or deleted while paging shift the window (items skipped or duplicated), and deep offsets are slow - the database scans and discards offset rows.
Client passes an opaque cursor marking where the last page ended: posts(first: 20, after: "..."). Stable under concurrent writes and fast at any depth (WHERE sort_key > cursor uses an index). Cost: no random page access, and cursors must encode the full sort key.
The standardized cursor shape most GraphQL APIs adopt: field returns a Connection { edges { cursor, node }, pageInfo { hasNextPage, endCursor } }. Verbose, but tooling (Relay, Apollo) understands it natively.
Cursor pagination for any feed, infinite scroll, or list that grows - it is the GraphQL default and the expected interview answer. Offset only for small, admin-style tables where jump-to-page matters more than consistency. If you adopt cursors, adopt the connection spec rather than inventing your own shape.