Pagination with chooseWindow() exists because ServiceNow will terminate any server-side script that runs too long, and large result sets will blow past those limits. The critical insight most developers miss: pagination is meaningless without a consistent sort order. Without orderBy(), your "pages" will contain random, overlapping, or missing records as the database returns results in whatever order it chooses. This isn't a ServiceNow quirk—it's fundamental database behavior that will bite you in production when records shift between pages.

When to use this pattern

  • Processing thousands of records in a Scheduled Job where each record needs individual business logic applied
  • Data migration scripts that must touch every record in a table but can't risk timeout
  • Fix Scripts where you need to examine field values and make conditional updates
  • Batch operations that call external APIs for each record and need to handle rate limiting gracefully

When NOT to use this pattern

  • Simple bulk updates where all records get the same value—use updateMultiple() instead for vastly better performance
  • Counting records or aggregate calculations—use GlideAggregate which handles large datasets without pagination
  • Building arrays or lists to return to client scripts—the client can't handle massive datasets anyway
  • Business Rules that fire on every record insert/update—you're already processing one record at a time

Key behaviors and gotchas

  • Window boundaries are inclusive: chooseWindow(0, 99) returns 100 records, not 99
  • Without orderBy(), database row ordering is undefined and will vary between queries, making pagination unreliable
  • ACL restrictions still apply—pagination won't bypass security, it may just return fewer records per page
  • Records inserted during pagination may be missed or duplicated depending on sort order and insertion point
  • The last page typically returns fewer than batch size records—this is how you detect the end condition
  • Order by indexed fields when possible (sys_created_on, sys_id) for better performance on large tables
⚠️

Never rely on sys_id ordering for business logic—sys_ids are not guaranteed to be chronologically ordered and vary between instances.

Free Newsletter

Enjoying this? Get one deep-dive per week.

Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.

No spam · Unsubscribe anytime