# Stripe pagination and expand: stop writing manual loops
Stripe list endpoints paginate. Agents write the pagination loop by hand, get the cursor wrong, and silently process half the customers. Both SDKs already solve this. Use them.
## Auto-pagination
- stripe-node: `stripe.customers.list().autoPagingEach((customer) => {...})` or `autoPagingToArray({limit: 10000})`. The SDK follows `has_more` and `starting_after` for you.
- stripe-python: `for customer in stripe.Customer.list().auto_paging_iter(): ...`.
- If you must paginate manually: loop while `has_more` is true, passing the last object's ID as `starting_after`. The two classic bugs are forgetting `starting_after` (infinite loop over page one) and stopping at `has_more` without fetching the final page.
## Expand
- `expand: ['data.default_payment_method']` pulls nested objects into the response, avoiding a second call per item. Use it for the one or two nested objects you always need.
- Do not expand deeply nested trees. Stripe caps expand depth, and a deeply expanded list response balloons in size and latency. If you find yourself expanding three levels, fetch the nested objects in a second pass instead.
- The N+1 trap: listing 100 invoices then fetching each customer individually is 101 calls. One list call with `expand: ['data.customer']` is one call. But expanding the customer on a 10,000-row auto-paginated walk can be slower than batching; measure before assuming.
## Rules
1. Default to auto-pagination. Manual cursor loops are a bug farm.
2. Expand one level for what you always need; fetch the rest separately.
3. Never put an unbounded auto-pagination walk in a request handler. Page through large collections in background jobs.