- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
If you're a ServiceNow developer in 2026, there's a good chance AI is writing at least some of your code. And there's an equally good chance that code defaults to GlideRecord. It works, mostly — until it doesn't, and the failures are the silent kind that slip into production without a trace.
That's the starting point for this conversation between Developer Advocate Sujan and Amit Gujarathi, a five-time ServiceNow MVP and Solution Architect with over 11 years in the ServiceNow ecosystem. Together they walk through GlideQuery on a live instance, showing exactly where it outperforms GlideRecord and why it deserves a permanent spot in your scripting toolkit.
GlideQuery Is Not a Replacement — It's a Safer Layer
First things first: GlideQuery is a wrapper around GlideRecord. Same engine, same database calls. The difference is in the interface it puts on top. Amit compared it this way — GlideRecord is like driving with no seat belts and no lane assist. It'll let you do anything, but if something goes wrong, you're on your own. GlideQuery adds guardrails that catch problems before they become incidents of a different kind.
The Typo That Deletes Everything
The first demo hit hard. A simple query filtering on an "activated" field (a typo for "active") was run with GlideRecord. No error. No warning. GlideRecord just ignored the invalid field and returned every record in the table. Now imagine that typo was in a deleteMultiple operation — you'd wipe the table clean without realising.
With GlideQuery, the same typo throws a clear error message: "unknown field 'activated' in table incident." Better yet, it lists all valid fields on the table so you can spot the correct name immediately. That's not just error handling — it's built-in time savings.
JavaScript Type Comparisons That Actually Work
The second scenario tackled a notoriously tricky bug. When you pull an email field from GlideRecord and compare it with triple-equals (===) to a plain string, the comparison fails even when the values are identical. That's because GlideRecord returns a GlideElement object, not a JavaScript string, so a strict type comparison will never match.
GlideQuery returns plain JavaScript values. Triple-equals works as expected. This eliminates a whole class of bugs that are painful to debug because the logged output looks perfectly correct.
Immutable Queries: Define Once, Extend Anywhere
With GlideRecord, if you need to run three queries that share a base condition (say, active equals true) but differ on priority, you end up copy-pasting that base condition into each one. Change the base later, and you have three places to update.
GlideQuery's query objects are immutable. You define your base condition once, then use .where() to create new query objects that extend it. The original stays untouched. Less code, fewer places for things to go wrong, and much easier maintenance.
Select Only What You Need
GlideRecord pulls the entire row every time. GlideQuery's .select() method lets you specify exactly which fields you want. On large tables, this is a meaningful performance improvement — you're only transferring the data you'll actually use.
The .selectOne() method goes further by returning an Optional. Instead of writing if-else blocks to handle missing records, you chain .orElse() with a default object. It's cleaner, more readable, and prevents widgets from crashing when data is missing.
Insert and Update with Plain JSON
Creating a record with GlideRecord means calling initialize(), then setValue() for each field, then insert(). With GlideQuery, you pass a JSON object directly to .insert(). Two lines instead of ten. For integrations where payloads arrive as JSON, this is a significant time saver — if your keys match the table's field names, you can pass the payload straight through.
Updates work similarly. Single-record updates require a sys_id (intentionally, to prevent accidental mass updates). Bulk updates accept a query plus a JSON object of changes. And the insertOrUpdate method handles the "upsert" pattern — check if a record exists, update it if it does, create it if it doesn't — in a single method call.
Aggregates Without GlideAggregate
This is where GlideQuery really separates itself. With GlideRecord, aggregation means switching to a separate GlideAggregate class. With GlideQuery, you chain .aggregate('COUNT') and .groupBy() right into your existing query. Count active incidents per category? Nine lines of code, and the calculation happens at the database level rather than pulling records into memory and counting with JavaScript.
The session also covered average calculations with .aggregate('AVG') grouped by state, and a two-dimensional grouping example (priority × state) that builds a structured report object ready for a portal widget or REST API response — all in a single fluent chain.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
