← Back to list

A Simple Guide to GlideRecord in ServiceNow

When I started learning ServiceNow development, one thing became clear very quickly: GlideRecord is everywhere.

Lakshmi Prasanna Diguvapatla · 2026-02-12 11:25 · 0 claps · 7.6 min read
#servicenow #servicenow-training #servicenow-integration #servicenow-online #servicenow-data-sync
Open on Medium ↗
Wiki topics: EDU · Education & Learning

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