A Simple Guide to GlideRecord in ServiceNow
When I started learning ServiceNow development, one thing became clear very quickly: GlideRecord is everywhere.
A Simple Guide to GlideRecord in ServiceNow
When I started learning ServiceNow development, one thing became clear very quickly: GlideRecord is everywhere.
Whether you’re writing a Business Rule, a Script Include, a Scheduled Job, or even debugging something in Background Scripts — GlideRecord is the tool you use to interact with the database.
Over time, I realised that understanding GlideRecord deeply doesn’t just make you a better developer — it makes you faster, more confident, and more capable of solving real business problems.
Let’s break GlideRecord down in a simple, practical way.
🌟 What Is GlideRecord?
GlideRecord is ServiceNow’s server‑side API that allows you to interact with database tables using JavaScript.
If SQL feels complicated, GlideRecord makes things easier. It lets you:
- Query records
- Insert new records
- Update existing records
- Delete records
- Apply filters
- Use encoded queries
- Join tables
- Work with display values
- Enforce ACLs (with GlideRecordSecure)
It’s the backbone of almost every backend script in ServiceNow.
🌟 Why GlideRecord Matters
You will use GlideRecord in:
- Business Rules
- Script Includes
- Scheduled Jobs
- Workflows
- Background Scripts
- Transform Maps
- Integrations
- Fix scripts
- Data cleanup tasks
It’s the foundation of automation and data manipulation on the platform.
If you understand GlideRecord well, you can build almost anything.
🌟 How GlideRecord Works (Simple Explanation)
GlideRecord follows a simple pattern:
1. Create a GlideRecord object
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
2. Add filters
gr.addQuery('priority', 1); // Add a filter: priority = 1 (Critical)
3. Execute the query
gr.query(); // Execute the query and fetch matching records
4. Loop through results
while (gr.next()) { // Loop through each returned record
gs.info(gr.number); // Log the incident number for visibility
}
This retrieves all P1 incidents and prints their numbers.
🌟 CRUD Operations With GlideRecord
CRUD = Create, Read, Update, Delete. Here’s how to perform each operation.
🟢 Create (Insert a new record)
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
gr.initialize(); // Prepare a new empty record with default values
gr.short_description = 'Created via GlideRecord'; // Set the short description for the new incident
gr.priority = 2; // Set priority (2 = High)
gr.insert(); // Insert the new record into the database
🔵 Read (Retrieve records)
Get by sys_id
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
if (gr.get('sys_id_value')) { // Try to retrieve the record by sys_id (returns true if found)
gs.info(gr.short_description); // Log the short description of the incident
} else {
gs.info('Record not found'); // Log a message if the sys_id does not match any record
}
Query multiple records
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
gr.addQuery('state', 1); // Add a filter: state = 1 (New)
gr.query(); // Execute the query and fetch matching records
while (gr.next()) { // Loop through each returned record
gs.info(gr.number); // Log the incident number for visibility
}
🟡 Update (Modify a record)
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
if (gr.get('sys_id_value')) { // Retrieve the record by sys_id (returns true if the record exists)
gr.state = 2; // Update the state field (2 = In Progress)
gr.update(); // Save the updated record to the database
}
🔴 Delete (Remove a record)
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
if (gr.get('sys_id_value')) { // Try to retrieve the record by sys_id (returns true if found)
gr.deleteRecord(); // Delete the record safely from the database
}
🌟 Encoded Queries
Encoded queries let you write compact, powerful filters.
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
gr.addEncodedQuery('priority=1^active=true'); // Add multiple conditions in one line (priority = 1 AND active = true)
gr.query(); // Execute the encoded query and fetch matching records
This retrieves all active P1 incidents.
🌟 OR Conditions & Complex Queries
To add OR conditions:
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
var qc = gr.addQuery('priority', 1); // First condition: priority = 1 (Critical)
qc.addOrCondition('priority', 2); // OR condition: priority = 2 (High)
gr.query(); // Execute the query and fetch matching records
This retrieves P1 or P2 incidents.
Let’s look at a real example where GlideRecord saves time in the real world.
🌟 Real‑Time Example: Bulk Reassigning Incidents
Here’s a real‑world scenario every ServiceNow admin or developer eventually faces:
John left the company yesterday. Before he left, he was handling 47 open incidents. Now Sarah needs to take over all of them — but doing this manually would mean opening each record, changing the Assigned to field, and saving it one by one.
That’s 30+ minutes of repetitive clicking.
This is exactly the kind of situation where GlideRecord saves time, reduces errors, and makes you look like a hero.
// When a user leaves, reassign all their open incidents
var gr = new GlideRecord('incident'); // Create a GlideRecord object for the 'incident' table
gr.addQuery('assigned_to', 'old_user_sys_id'); // Find incidents currently assigned to the old user (John)
gr.addQuery('active', true); // Only include active (open) incidents
gr.query(); // Execute the query and fetch matching records
var count = 0; // Counter to track how many incidents were updated
while (gr.next()) { // Loop through each matching incident
gr.assigned_to = 'new_user_sys_id'; // Reassign the incident to the new user (Sarah)
gr.update(); // Save the updated record to the database
count++; // Increment the counter
}
gs.info('Reassigned ' + count + ' incidents'); // Log how many incidents were reassigned
Result
47 incidents reassigned in seconds. This is the kind of automation ServiceNow developers rely on every day — fast, reliable, and error‑free.
Try It Yourself
- Run this script in Background Scripts on your Personal Developer Instance
- Use
gs.info()to watch the progress in the logs - Start with
setLimit(5)while learning, so you don’t accidentally update too many records - Once confident, remove the limit and run it for real
🌟 Display Values vs Actual Values
A common beginner confusion:
When you look at an incident in ServiceNow:
- Priority shows as “1 — Critical” (this is the display value)
- But in the database, it’s stored as “1” (this is the actual value)
getValue() → gets the database value
gr.getValue('priority'); // returns "1"
getDisplayValue() → returns the human‑readable value
gr.getDisplayValue('priority'); // returns "1 - Critical"
This is extremely useful when working with choice fields, references, or logs.
🌟 Best Practices for Beginners
✔ Use get() when querying by sys_id
It’s faster and cleaner.
✔ Use setLimit() for large tables
Avoid loading thousands of records.
✔ Use indexed fields in queries
Better performance.
✔ Use addEncodedQuery() for complex filters
Cleaner and easier to maintain.
✔ Avoid querying inside loops
This slows down performance.
✔ Use initialize() before insert
Prevents unexpected field values.
🌟 Common Mistakes to Avoid
❌ Mistake #1: Forgetting to Call query()
The Problem:
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
// FORGOT gr.query() here!
while (gr.next()) { // This never runs because query() wasn't called!
gs.info(gr.number);
}
Why it fails: You set up the query with addQuery(), but never executed it. The next() loop has nothing to iterate over.
✅ Fixed:
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.query(); // Must call this to execute the query!
while (gr.next()) {
gs.info(gr.number); // Now this works!
}
❌ Mistake #2: Not Checking if Record Exists
The Problem:
var gr = new GlideRecord('incident');
gr.get('invalid_sys_id');
gr.state = 2; // This does nothing if record doesn't exist!
gr.update(); // Silent failure - no error, but nothing happens
Why it fails: If get() doesn't find the record, the GlideRecord object is empty. Any updates are ignored.
✅ Fixed:
var gr = new GlideRecord('incident');
if (gr.get('sys_id_value')) { // Always check if record was found!
gr.state = 2;
gr.update();
gs.info('Updated successfully');
} else {
gs.info('Record not found');
}
❌ Mistake #3: Using next() Without Proper Loop Structure
The Problem:
var gr = new GlideRecord('incident');
gr.addQuery('priority', 1);
gr.query();
gr.next(); // Only processes the FIRST record
gs.info(gr.number); // Only see one incident
gr.next(); // Have to manually call next() again
gs.info(gr.number); // This is tedious and error-prone
Why it fails: Without a while loop, you only process one record at a time and have to manually call next() repeatedly.
✅ Fixed:
var gr = new GlideRecord('incident');
gr.addQuery('priority', 1);
gr.query();
while (gr.next()) { // Loop through ALL matching records automatically
gs.info(gr.number);
}
❌ Mistake #4: Not Using initialize() Before insert()
The Problem:
var gr = new GlideRecord('incident');
// FORGOT gr.initialize() here!
gr.short_description = 'Test incident';
gr.priority = 2;
gr.insert();
// Record created, but missing default values like caller_id, opened_at, etc.
Why it fails: Without initialize(), default values from the table definition aren't set. Fields that should auto-populate stay empty.
✅ Fixed:
var gr = new GlideRecord('incident');
gr.initialize(); // Sets all default values from table definition
gr.short_description = 'Test incident';
gr.priority = 2;
gr.insert(); // Now has all proper defaults!
❌ Mistake #5: Querying Inside Loops (Performance Killer!)
The Problem:
// BAD: Creates hundreds of database queries!
var gr1 = new GlideRecord('incident');
gr1.addQuery('active', true);
gr1.query();
while (gr1.next()) {
// DON'T DO THIS - Query inside a loop!
var gr2 = new GlideRecord('sys_user');
gr2.get(gr1.assigned_to); // Separate query for EACH incident
gs.info('Assigned to: ' + gr2.name);
}
// If you have 500 incidents, this creates 500 queries = SLOW!
Why it fails: Each iteration creates a new database query. With 100 incidents, you’re making 100 queries instead of 1.
✅ Fixed (Method 1 — Use Display Value):
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.query();
while (gr.next()) {
// Just use getDisplayValue() - no extra query needed!
gs.info('Assigned to: ' + gr.getDisplayValue('assigned_to'));
}
✅ Fixed (Method 2 — Collect IDs First):
// Step 1: Collect all user IDs
var userIds = [];
var gr1 = new GlideRecord('incident');
gr1.addQuery('active', true);
gr1.query();
while (gr1.next()) {
var userId = gr1.getValue('assigned_to');
if (userId && userIds.indexOf(userId) == -1) {
userIds.push(userId);
}
}
// Step 2: Query users once with IN operator
var userMap = {};
var gr2 = new GlideRecord('sys_user');
gr2.addQuery('sys_id', 'IN', userIds.join(','));
gr2.query();
while (gr2.next()) {
userMap[gr2.sys_id.toString()] = gr2.name.toString();
}
// Step 3: Use the map
gs.info('Users found: ' + JSON.stringify(userMap));
❌ Mistake #6: Fetching Unnecessary Fields (Performance Issue)
The Problem:
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.query();
while (gr.next()) {
// You only need the number, but GlideRecord fetches ALL fields
// (short_description, caller_id, assignment_group, work_notes, etc.)
gs.info(gr.number);
}
// Wasted bandwidth and memory!
Why it’s bad: By default, GlideRecord fetches every field in the table, even if you only use one or two.
✅ Fixed:
// Use setLimit() to reduce number of records fetched
var gr = new GlideRecord('incident');
gr.addQuery('state', 1);
gr.setLimit(100); // Only fetch first 100 records
gr.query();
while (gr.next()) {
gs.info(gr.number);
}
Note: There’s no built-in way to select specific fields in GlideRecord (unlike SQL’s SELECT). Always use setLimit() when you don't need all results.
❌ Updating records without checking ACLs
Use GlideRecordSecure when scripts run for non‑admin users.
❌ Using GlideRecord in client scripts
GlideRecord is server‑side only. Client scripts must use GlideAjax instead.
How to Test Your Scripts Safely
🧪 Test in Background Scripts
- Go to System Definition → Scripts — Background
- Run your GlideRecord code here first
- Add
gs.info()statements to see what’s happening
📝 Check the System Log
- Navigate to System Logs → System Log → All
- Look for errors or your
gs.info()messages - Filter by your script name or timestamp
Avoiding these mistakes will save you hours of debugging.
🌟 Final Thoughts
GlideRecord is one of the most essential skills for any ServiceNow developer. Once you understand how it works, you can:
- Build reliable automation
- Write cleaner, more maintainable scripts
- Improve performance with better queries
- Solve real‑world problems with confidence
🌟 Your Turn
You’ve learned the fundamentals of GlideRecord — now it’s time to practice.
Action Steps
- Get a ServiceNow Personal Developer Instance (free)
- Navigate to ALL > System Definition > Scripts — Background
- Copy and run each example from this article
- Modify them — change table names, add conditions, experiment
- Break things and fix them — that’s how you learn
Thanks for reading — I hope this was helpful.
메타데이터
- post_id
- 891fb63cf3e1
- slug
- a-simple-guide-to-gliderecord-in-servicenow-891fb63cf3e1
- url
- https://medium.com/@lakshmiprasanna123/a-simple-guide-to-gliderecord-in-servicenow-891fb63cf3e1
- canonical_url
- https://medium.com/@lakshmiprasanna123/a-simple-guide-to-gliderecord-in-servicenow-891fb63cf3e1
- author_url
- https://medium.com/@lakshmiprasanna123
- status
- ok
- fetched_at
- 2026-07-29 00:11:46