ServiceNow GlideRecord API
GlideRecord is the primary JavaScript API for reading and writing data in ServiceNow's database. Every server-side script that touches records — Business Rules, Script Includes, Scheduled Jobs, and REST APIs — uses GlideRecord. Mastering this API is the single most important developer skill in ServiceNow.
What GlideRecord Does
GlideRecord lets scripts interact with any table in the database. A script uses GlideRecord to find records, read their field values, update them, create new records, or delete them — all in JavaScript without writing raw SQL queries.
Database Table: incident
GlideRecord does the same job as SQL, but in JavaScript:
SQL: SELECT * FROM incident WHERE state = 1
GlideRecord:
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.query();
Reading Records: The Basic Query Pattern
Every GlideRecord query follows the same four-step pattern: create the object, add conditions, execute the query, loop through results.
// Step 1: Create GlideRecord object targeting the 'incident' table
var gr = new GlideRecord('incident');
// Step 2: Add filter conditions (like a WHERE clause)
gr.addQuery('state', 1); // State = New
gr.addQuery('priority', 1); // AND Priority = Critical
// Step 3: Execute the query
gr.query();
// Step 4: Loop through each matching record
while (gr.next()) {
gs.log('Incident: ' + gr.number + ' — ' + gr.short_description);
}
Common Query Methods
addQuery(field, value)
Adds a filter condition using exact equality. Multiple addQuery calls combine with AND logic — all conditions must match.
addQuery(field, operator, value)
Adds a filter with a specific operator. Operators include: CONTAINS, STARTSWITH, ENDSWITH, IN, NOT IN, greater than, less than, INSTANCEOF.
gr.addQuery('short_description', 'CONTAINS', 'VPN');
gr.addQuery('priority', 'IN', '1,2');
gr.addQuery('opened_at', '>=', gs.daysAgoStart(7));
addOrCondition(field, value)
Connects conditions with OR instead of AND. This must chain onto an existing addQuery call.
var stateQ = gr.addQuery('state', 1); // State = New
stateQ.addOrCondition('state', 2); // OR State = In Progress
orderBy(field) and orderByDesc(field)
Sorts query results. orderBy sorts ascending, orderByDesc sorts descending.
gr.orderBy('priority'); // Lowest priority number first (Critical)
gr.orderByDesc('opened_at'); // Newest records first
setLimit(n)
Caps how many records the query returns. Use this to prevent scripts from processing thousands of records unintentionally.
gr.setLimit(10); // Return only the first 10 matching records
Reading Field Values
Inside the while loop, access field values using the GlideRecord object's field names:
while (gr.next()) {
var num = gr.getValue('number'); // Stored value (string)
var desc = gr.getValue('short_description'); // String field value
var priority = gr.getValue('priority'); // Stored value: "1"
var priorityLabel = gr.getDisplayValue('priority'); // "1 - Critical"
var assignedTo = gr.getDisplayValue('assigned_to'); // "John Smith"
}
Creating a New Record
var newInc = new GlideRecord('incident');
newInc.initialize(); // Prepare a blank record
newInc.setValue('short_description', 'Server CPU at 100%');
newInc.setValue('priority', 1);
newInc.setValue('category', 'infrastructure');
newInc.setValue('assignment_group',
gs.getGroupByName('Network Support')); // Set by group name
var sysId = newInc.insert(); // Save and return sys_id
gs.log('Created incident: ' + sysId);
Updating Existing Records
var gr = new GlideRecord('incident');
gr.get('INC0001234'); // Get record by number or sys_id
gr.setValue('state', 6); // Set State = Resolved
gr.setValue('close_notes', 'Issue resolved after server reboot.');
gr.update(); // Save the changes
Deleting Records
var gr = new GlideRecord('incident');
gr.addQuery('state', 7); // Closed incidents
gr.addQuery('resolved_at', '<', gs.daysAgoEnd(365)); // Over 1 year old
gr.query();
while (gr.next()) {
gr.deleteRecord();
}
GlideRecord.get() Shortcut
When fetching exactly one record by its sys_id or by a unique field value, use the get() shortcut instead of query() plus next():
var gr = new GlideRecord('incident');
if (gr.get('abc123def456...')) { // sys_id
gs.log(gr.short_description);
}
// Or get by a unique field:
if (gr.get('number', 'INC0001234')) {
gs.log(gr.state);
}
GlideAggregate: Counting Without Loading Records
When a script only needs a count or sum — not individual records — GlideAggregate is far more efficient than GlideRecord because it returns the calculation without loading record data into memory.
var agg = new GlideAggregate('incident');
agg.addQuery('state', 'NOT IN', '6,7'); // Not Resolved or Closed
agg.addAggregate('COUNT');
agg.query();
if (agg.next()) {
var openCount = agg.getAggregate('COUNT');
gs.log('Open incidents: ' + openCount);
}
Performance Tips
- Always use addQuery conditions to filter records — never load all records and filter in the while loop.
- Use setLimit() when you only need a fixed number of records.
- Use GlideAggregate for counts and sums instead of GlideRecord loops.
- Avoid running GlideRecord queries inside a while loop that iterates through another GlideRecord — this creates N+1 query problems that destroy performance on large data sets.
