Offset pagination (LIMIT/OFFSET) is fine until it isn’t: it gets slow on large tables and it produces weird duplicates when rows are inserted between pages. For APIs I prefer cursor pagination with an opaque token. The token encodes the last seen (created_at, id) and the query uses that tuple for stable ordering. The important detail is the “tie breaker” field (id) so you never skip rows when multiple items share the same timestamp. I make the cursor opaque by base64-encoding JSON; you can also sign it if tampering matters. This pattern keeps DB performance predictable and makes frontend infinite scroll stable. It’s also easier to cache because page boundaries don’t shift as data changes.