ServiceNow executes orderBy() and orderByDesc() calls as MySQL ORDER BY clauses in the sequence you call them β€” not the sequence you'd logically expect. The first orderBy() call becomes the primary sort, each subsequent call becomes a tiebreaker. This means you can't reorder or modify the sort criteria after calling query() β€” the database has already executed and returned sorted results. Developers often assume they can sort in JavaScript after querying, but processing 10,000+ records client-side will kill your transaction time.

When to use this pattern

  • Processing records in priority sequence within Business Rules or Scheduled Jobs
  • Generating reports where row order matters (oldest incidents first, highest priority tickets)
  • Batch processing where you need consistent ordering across multiple script executions
  • Early exit scenarios where you only need the first N records in a specific order

When NOT to use this pattern

  • Client-side scripts β€” use GlideAjax with server-side sorting instead
  • Large result sets (>1000 records) on non-indexed fields β€” you'll timeout the database
  • When you only need aggregated data β€” use GlideAggregate with orderBy() instead
  • Inside loops over other GlideRecords β€” you're creating N+1 query scenarios that will crash under load

Key behaviors and gotchas

  • Chaining multiple orderBy() calls creates multilevel sorting β€” first call is primary, subsequent calls break ties
  • Choice field sorting uses display values, not underlying integers β€” priority sorts as "1-Critical", "2-High" alphabetically
  • Reference field sorting uses the display field of the referenced table, not the sys_id value
  • Sorting on non-indexed fields forces full table scans β€” description and work_notes will kill performance
  • ACLs still apply to sorted results β€” users only see records they have read access to, in the specified order
  • Domain separation affects sort order β€” records from different domains may sort differently based on field visibility
⚠️

Never sort by journal fields (work_notes, comments, activity_due) β€” they're stored in separate tables and will either fail silently or create massive JOIN queries that timeout.