---
title: Pagination and iteration
description: Traverse authorized account pages with query-bound cursors, lazy iteration, cancellation, and explicit page and item limits.
---

`social.accounts.list` returns one `Page<AccountRecord>`. A page contains `items` and may contain `nextCursor`. Pass that cursor unchanged with the same backend, tenant authorization, and page size to read the next page.

The client wraps provider cursors with their query scope. Switching the backend, tenant, or `limit` while reusing a cursor fails locally before the adapter runs. A cursor carries navigation state, not an authorization grant. The application still authorizes the accounts on every returned page. Avoid logging cursor contents because an upstream cursor may contain provider query details.

## Iterate authorized accounts

`social.accounts.iterate` is lazy. Constructing its iterator does not fetch anything; requests begin when iteration starts. It uses the same account authorization policy as `list`.

```ts
import { createSocial } from "@opencoredev/social-sdk";
import { mockBackend } from "@opencoredev/social-sdk/testing";

const social = createSocial({ backend: mockBackend() });
const controller = new AbortController();
for await (const account of social.accounts.iterate({
  backend: "default",
  limit: 25,
  maxPages: 10,
  maxItems: 100,
  signal: controller.signal,
})) {
  console.log(account.displayName);
}
```

This complete mock example prints `Mock Creator` and `Mock Studio` without network calls. For a real multi-user client, pass the authenticated session in the iterator's `authorization` option and configure the client's authorization policy. Keep provider credentials on the server. See the [mock quickstart](/getting-started/mock-quickstart) for publication setup.

The default limits are 100 pages and 10,000 items. Reaching either limit ends iteration even if the backend has more results. Use explicit `list` calls when you need to retain a continuation cursor. Breaking out of the loop stops additional page requests. Aborting the signal interrupts traversal and passes cancellation to the active adapter request. Repeated or empty upstream cursors fail rather than creating an infinite loop.

## Other page sources

The exported `iterateItems` helper accepts a callback that reads one page from a cursor. It supplies the same lazy traversal, repeat detection, and bounds. Pass the signal to both the helper and your underlying read operation. This helper does not add pagination to an adapter operation that only reads its first page.

Account pagination and iteration have deterministic tests under Node and Bun. Provider list endpoints may still have upstream history limits or changing results between requests. A completed traversal is a view of those responses, not a transactionally consistent snapshot.

## Feeds, search, comments, and conversations

`posts.list(account, options)`, `social.search.posts(account, options)`, `comments.list(post, options)`, `messages.listConversations(account, options)`, `messages.listMessages(conversation, options)`, `notifications.list(account, options)`, and `graph.listRelationships(account, options)` accept `cursor` and `limit`. Their cursors bind the backend, tenant, account, resource, query where applicable, relationship kind, and page size. Pass the returned value unchanged. An adapter with no upstream continuation rejects a supplied cursor instead of returning page one again.

Use `posts.iterate`, `search.iteratePosts`, `comments.iterate`, `messages.iterateConversations`, `messages.iterateMessages`, or `notifications.iterate` for lazy bounded traversal. `graph.listRelationships` is page-based. Each iterator accepts the same `maxPages`, `maxItems`, and cancellation controls as account iteration. The capability manifest identifies which adapters implement each list operation.

Search cursors are provider cursors, not durable checkpoints. A provider may add, remove, or reorder matches while a query is being traversed. Persist a cursor only with the exact query and request scope that produced it, and stop when the provider omits `nextCursor`.
