<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>question GlideRecord &amp;amp; GlideAjax in ServiceNow: Client-Side vs Server-Side in Community Central forum</title>
    <link>https://www.servicenow.com/community/community-central-forum/gliderecord-amp-glideajax-in-servicenow-client-side-vs-server/m-p/3579857#M7569</link>
    <description>&lt;P&gt;When you start building real-world ServiceNow solutions, one of the most important distinctions to understand is the difference between client-side and server-side execution. A lot of confusion in ServiceNow development comes from using the right API in the wrong place, or from making synchronous calls that slow the user experience.&lt;/P&gt;&lt;P&gt;In this article, we will walk through:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;how client-side GlideRecord works,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;why callback functions matter,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how GlideAjax connects the client to the server,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to build client-callable Script Includes,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to return multiple values,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to work with reference fields safely,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to use encoded queries on the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and when JSON is the better way to return structured data.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;1) Understanding Client-Side GlideRecord&lt;/H2&gt;&lt;P&gt;GlideRecord is a ServiceNow API object used to interact with the database. On the client side, it allows a script running in the browser to query records from the server. That sounds convenient, but it comes with a performance cost.&lt;/P&gt;&lt;P&gt;Client scripts run in the user’s browser when a page loads, a field changes, or a form is submitted. If a client script makes the browser wait for the server, the user experience becomes slower and less responsive. This is why synchronous calls from the client are usually discouraged, especially on page load or on field change.&lt;/P&gt;&lt;P&gt;A useful rule of thumb is this:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;use client-side scripts for lightweight browser logic,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;use server-side logic for database work,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and use asynchronous calls whenever possible.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;2) Why Callback Functions Matter&lt;/H2&gt;&lt;P&gt;A callback function allows a query to be executed asynchronously. Instead of freezing the browser while waiting for a response, the script submits the request to the server and continues running. When the response returns, the callback function is executed.&lt;/P&gt;&lt;P&gt;That difference is important.&lt;/P&gt;&lt;H3&gt;Without a callback&lt;/H3&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;Submit the query to the database.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server processes the query.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server builds the response.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The response returns to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional client-side work happens.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The user can finally interact with the page.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;H3&gt;With a callback&lt;/H3&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;Submit the query to the database.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;A class="" href="https://www.servicenow.com/community/community-central-forum/bd-p/community-central-forum" target="_blank" rel="noopener"&gt;Community Central forum&lt;/A&gt;The user can keep interacting with the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server processes the query.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server builds the response.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The response returns to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The callback function runs.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional client-side work happens inside the callback.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;That second flow is usually much better for performance.&lt;/P&gt;&lt;H3&gt;Example: asynchronous GlideRecord query&lt;/H3&gt;&lt;PRE&gt;var gr = new GlideRecord('a_table');
gr.addQuery('some', 'conditions');
gr.query(myCallBack);

// define the callback function
function myCallBack(gr) {
    while (gr.next()) {
        // do some client-side work
    }
}&lt;/PRE&gt;&lt;P&gt;The same idea applies to g_form.getReference():&lt;/P&gt;&lt;PRE&gt;g_form.getReference('assigned_to', cbFunc);

function cbFunc(gr) {
    var assignedToName = gr.getValue('name');
    alert('This ticket is assigned to: ' + assignedToName + '.');
}&lt;/PRE&gt;&lt;P&gt;In both cases, the browser stays responsive while the server does the heavier work.&lt;/P&gt;&lt;H2&gt;3) GlideAjax: The Server-Side Bridge for Client Scripts&lt;/H2&gt;&lt;P&gt;GlideAjax is one of the most useful but least understood APIs in ServiceNow because it has both a client-side part and a server-side part.&lt;/P&gt;&lt;P&gt;It is not simply a replacement for GlideRecord. Instead, it is a way to send a request from the browser to the server, run a Script Include there, and send data back to the client.&lt;/P&gt;&lt;P&gt;That makes GlideAjax especially useful when you need to:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;query data from the database,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;return a value to the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;avoid synchronous client-side database access,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;or return structured data back to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;The response from GlideAjax is XML, and that means it can hold more than one value.&lt;/P&gt;&lt;H2&gt;4) GlideAjax From the Client&lt;/H2&gt;&lt;P&gt;A basic GlideAjax call starts in the client script.&lt;/P&gt;&lt;H3&gt;Example: client-side GlideAjax&lt;/H3&gt;&lt;PRE&gt;var ga = new GlideAjax('AjaxScriptInclude'); // exact Script Include name
ga.addParam('sysparm_name', 'greetingFunction'); // function to run
ga.addParam('sysparm_my_name', 'Tim'); // optional parameter
ga.getXML(myCallBack); // callback for the response

function myCallBack(response) {
    var greeting = response.responseXML.documentElement.getAttribute('answer');
    alert(greeting);
}&lt;/PRE&gt;&lt;H3&gt;What each line does&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;new GlideAjax('AjaxScriptInclude') tells ServiceNow which Script Include to call.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;sysparm_name identifies the function inside the Script Include.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional parameters, such as sysparm_my_name, can be passed into the server-side function.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;getXML(myCallBack) sends the request and handles the result asynchronously.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;The response variable contains XML, and the returned value is usually available through the answer attribute:&lt;/P&gt;&lt;PRE&gt;var greeting = response.responseXML.documentElement.getAttribute('answer');&lt;/PRE&gt;&lt;P&gt;That is the standard pattern when the Script Include returns a single value.&lt;/P&gt;&lt;H2&gt;5) Building the GlideAjax Script Include&lt;/H2&gt;&lt;P&gt;To make GlideAjax work, the server-side Script Include must be client callable and must extend AbstractAjaxProcessor.&lt;/P&gt;&lt;H3&gt;Example: server-side Script Include&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        return 'Hiya, ' + userName + '.';
    }
});&lt;/PRE&gt;&lt;H3&gt;Important points&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;The Script Include name must match the client-side name.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;sysparm_name tells ServiceNow which function to run.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;this.getParameter('sysparm_my_name') retrieves the parameter passed from the client.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The function runs on the server, so you can use server-side APIs and database access there.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;6) Private Functions in GlideAjax Script Includes&lt;/H2&gt;&lt;P&gt;Not every function in a Script Include should be callable from the client. Sometimes you want helper logic that stays internal.&lt;/P&gt;&lt;P&gt;If the Script Include extends AbstractAjaxProcessor, a function name starting with an underscore is treated as private.&lt;/P&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        var msg = this._getMsg(userName);
        return msg;
    },

    _getMsg: function(userName) {
        return 'Hey there, ' + userName + '.';
    }
});&lt;/PRE&gt;&lt;P&gt;Here:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;greetingFunction() is the public function called by GlideAjax.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;_getMsg() is a private helper used only inside the Script Include.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This is a clean way to separate callable logic from internal utility logic.&lt;/P&gt;&lt;H2&gt;7) Returning Multiple Values from GlideAjax&lt;/H2&gt;&lt;P&gt;Since GlideAjax returns XML, one approach is to create additional XML nodes and attach attributes to them. This lets you return more than one value from the server.&lt;/P&gt;&lt;P&gt;The notes show an example returning greetings in English, French, and Spanish.&lt;/P&gt;&lt;H3&gt;Server-side example&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        this._getEnglishMsg(userName);
        this._getFrenchMsg(userName);
        this._getSpanishMsg(userName);
    },

    _getEnglishMsg: function(userName) {
        var greeting = 'Howdy, ' + userName + '. How are you?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'English');
        msg.setAttribute('value', greeting);
    },

    _getFrenchMsg: function(userName) {
        var greeting = 'Bonjour, ' + userName + '. Ça va?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'French');
        msg.setAttribute('value', greeting);
    },

    _getSpanishMsg: function(userName) {
        var greeting = 'Hola, ' + userName + '. Cómo estás?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'Spanish');
        msg.setAttribute('value', greeting);
    }
});&lt;/PRE&gt;&lt;H3&gt;Client-side example&lt;/H3&gt;&lt;PRE&gt;var ga = new GlideAjax('AjaxScriptInclude');
ga.addParam('sysparm_name', 'greetingFunction');
ga.addParam('sysparm_my_name', 'Tim');
ga.getXML(myCallBack);

function myCallBack(response) {
    var language;
    var grtng;
    var greetings = response.responseXML.getElementsByTagName('greeting');

    for (var i = 0; i &amp;lt; greetings.length; i++) {
        language = greetings[i].getAttribute('lang');
        grtng = greetings[i].getAttribute('value');
        console.log(language + ': ' + grtng);
    }
}&lt;/PRE&gt;&lt;P&gt;This works, but it is often more complex than needed. A simpler modern pattern is to return an object as JSON and parse it on the client.&lt;/P&gt;&lt;H2&gt;&lt;span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"&gt;😎&lt;/span&gt; Why JSON Is Often the Better Option&lt;/H2&gt;&lt;P&gt;If you need to return multiple values, JSON is often easier to maintain than raw XML node handling. It gives you a structured payload that is more readable for developers and easier to expand later.&lt;/P&gt;&lt;P&gt;The basic pattern is:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;build an object or array on the server,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;encode it as a JSON string,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;return it through GlideAjax,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;parse it on the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;use the values in the UI.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;The notes also mention that in scoped applications, JSON.stringify() and JSON.parse() should be used instead of older global-scope methods.&lt;/P&gt;&lt;H2&gt;9) Return a Simple Object Using JSON&lt;/H2&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleObject: function() {
        var obj = {};
        var sysId = this.getParameter('sysparm_sys_id');

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addQuery('sys_id', sysId);
        almAssetGr.query();

        if (almAssetGr.next()) {
            obj.model = almAssetGr.getDisplayValue('model');
            obj.model_category = almAssetGr.getDisplayValue('model_category');

            var json = new JSON();
            var data = json.encode(obj);
        }

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleObject');
    ga.addParam('sysparm_sys_id', g_form.getValue('sys_id'));
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);
    g_form.addInfoMessage('Asset Model: ' + answer.model);
    g_form.addInfoMessage('Asset Category: ' + answer.model_category);
}&lt;/PRE&gt;&lt;P&gt;This is a neat pattern when you want to send a small set of related fields back to the client.&lt;/P&gt;&lt;H2&gt;10) Return a Simple Array Using JSON&lt;/H2&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleArray: function() {
        var obj = [];
        var sysId = this.getParameter('sysparm_sys_id');

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addQuery('sys_id', sysId);
        almAssetGr.query();

        if (almAssetGr.next()) {
            obj[0] = almAssetGr.getDisplayValue('model');
            obj[1] = almAssetGr.getDisplayValue('model_category');

            var json = new JSON();
            var data = json.encode(obj);
        }

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleArray');
    ga.addParam('sysparm_sys_id', g_form.getValue('sys_id'));
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);

    for (var i = 0; i &amp;lt; answer.length; i++) {
        g_form.addInfoMessage(answer[i]);
    }
}&lt;/PRE&gt;&lt;P&gt;This is useful when the returned data is ordered rather than named.&lt;/P&gt;&lt;H2&gt;11) Return an Array of Objects Using JSON&lt;/H2&gt;&lt;P&gt;This is one of the most useful patterns when you need to send a list of structured rows to the client.&lt;/P&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleJSONObject: function() {
        var obj = [];
        var sysIds = '1bc1fa8837f3100044e0bfc8bcbe5d48,1fc1fa8837f3100044e0bfc8bcbe5d50,ffa96c0d3790200044e0bfc8bcbe5d87';

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addEncodedQuery('sys_idIN' + sysIds);
        almAssetGr.query();

        while (almAssetGr.next()) {
            var payload = {};
            payload.model = almAssetGr.getDisplayValue('model');
            payload.model_category = almAssetGr.getDisplayValue('model_category');

            obj.push(payload);
        }

        var json = new JSON();
        var data = json.encode(obj);

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleJSONObject');
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);

    for (var i = 0; i &amp;lt; answer.length; i++) {
        g_form.addInfoMessage(answer[i].model + " - " + answer[i].model_category);
    }
}&lt;/PRE&gt;&lt;P&gt;This is a practical pattern for returning row-style data such as assets, users, incidents, tasks, or catalog-related metadata.&lt;/P&gt;&lt;H2&gt;12) Reference Fields and Display Values&lt;/H2&gt;&lt;P&gt;A common problem in client scripts is setting a reference field value. A reference field query often triggers a synchronous server call, which can lock the browser briefly.&lt;/P&gt;&lt;P&gt;The notes point out a useful workaround: when setting a reference field, provide both the sys_id and the display value.&lt;/P&gt;&lt;PRE&gt;g_form.setValue('some_ref_field', varContainingSysID, 'The Display Value');&lt;/PRE&gt;&lt;P&gt;This helps the form avoid extra unnecessary work and gives the field a proper display label immediately.&lt;/P&gt;&lt;H2&gt;13) Client-Side Encoded Queries&lt;/H2&gt;&lt;P&gt;Another useful trick is that client-side GlideRecord does not support addEncodedQuery() the same way server-side GlideRecord does. However, if you call addQuery() with a single argument, that argument is treated as an encoded query.&lt;/P&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;var gr = new GlideRecord('table_name');
gr.addQuery('active=true^approval=approved^assigned_to=62826bf03710200044e0bfc8bcbe5df1');
gr.query();

while (gr.next()) {
    // do some work
}&lt;/PRE&gt;&lt;P&gt;This can be very helpful when you need to keep a client-side query compact, especially when the logic is too complex for separate chained conditions.&lt;/P&gt;&lt;H2&gt;14) GlideRecord and JavaScript Operators&lt;/H2&gt;&lt;P&gt;The addQuery() method can accept different styles of input:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;one argument: encoded query,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;two arguments: field and value,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;three arguments: field, operator, value.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;gr.addQuery('number', 'STARTSWITH', 'INC');&lt;/PRE&gt;&lt;P&gt;Some commonly used operators include:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;gt;&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;lt;&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;gt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;lt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;!=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;STARTSWITH&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;ENDSWITH&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;CONTAINS&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;DOES NOT CONTAIN&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;IN&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;INSTANCEOF&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Examples:&lt;/P&gt;&lt;PRE&gt;gr.addQuery('short_description', 'CONTAINS', 'Help');
gr.addQuery('sys_class_name', 'INSTANCEOF', 'task');&lt;/PRE&gt;&lt;P&gt;These operators make your queries much more expressive and precise.&lt;/P&gt;&lt;H2&gt;15) Best Practice Summary&lt;/H2&gt;&lt;P&gt;Here is the core guidance from this article in one place:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Avoid synchronous client-side database work when possible.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use callback functions for asynchronous client-side queries.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use GlideAjax when a client script needs server-side data.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Keep server-side logic inside client-callable Script Includes.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use private helper methods inside Script Includes when logic should not be exposed.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Prefer JSON when returning structured or multiple values.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use display values when setting reference fields.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use encoded queries carefully on the client.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Choose the right query operator for readable and efficient conditions.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;16) Final Thoughts&lt;/H2&gt;&lt;P&gt;GlideRecord, GlideAjax, and callback functions are not just separate APIs. They are pieces of a larger performance strategy.&lt;/P&gt;&lt;P&gt;If you think in terms of browser responsiveness, server responsibility, and data shape, the whole design becomes much cleaner:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;let the browser stay light,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;let the server do the heavy lifting,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and return only the data the client truly needs.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;That approach will make your ServiceNow solutions faster, easier to maintain, and much more professional in real-world use.&lt;/P&gt;&lt;HR /&gt;&lt;P&gt;If you are building client-side functionality in ServiceNow, GlideAjax is usually the safest and cleanest bridge between the browser and the server. And when you need richer data, JSON is often the most maintainable way to return it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Feel Free To Follow Me on LinkedIn :&amp;nbsp;&lt;A href="https://www.linkedin.com/in/shaah/" target="_blank" rel="noopener"&gt;https://www.linkedin.com/in/shaah/&lt;/A&gt;&lt;/P&gt;</description>
    <pubDate>Tue, 28 Jul 2026 03:43:03 GMT</pubDate>
    <dc:creator>AL-Khalid</dc:creator>
    <dc:date>2026-07-28T03:43:03Z</dc:date>
    <item>
      <title>GlideRecord &amp; GlideAjax in ServiceNow: Client-Side vs Server-Side</title>
      <link>https://www.servicenow.com/community/community-central-forum/gliderecord-amp-glideajax-in-servicenow-client-side-vs-server/m-p/3579857#M7569</link>
      <description>&lt;P&gt;When you start building real-world ServiceNow solutions, one of the most important distinctions to understand is the difference between client-side and server-side execution. A lot of confusion in ServiceNow development comes from using the right API in the wrong place, or from making synchronous calls that slow the user experience.&lt;/P&gt;&lt;P&gt;In this article, we will walk through:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;how client-side GlideRecord works,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;why callback functions matter,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how GlideAjax connects the client to the server,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to build client-callable Script Includes,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to return multiple values,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to work with reference fields safely,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;how to use encoded queries on the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and when JSON is the better way to return structured data.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;1) Understanding Client-Side GlideRecord&lt;/H2&gt;&lt;P&gt;GlideRecord is a ServiceNow API object used to interact with the database. On the client side, it allows a script running in the browser to query records from the server. That sounds convenient, but it comes with a performance cost.&lt;/P&gt;&lt;P&gt;Client scripts run in the user’s browser when a page loads, a field changes, or a form is submitted. If a client script makes the browser wait for the server, the user experience becomes slower and less responsive. This is why synchronous calls from the client are usually discouraged, especially on page load or on field change.&lt;/P&gt;&lt;P&gt;A useful rule of thumb is this:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;use client-side scripts for lightweight browser logic,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;use server-side logic for database work,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and use asynchronous calls whenever possible.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;2) Why Callback Functions Matter&lt;/H2&gt;&lt;P&gt;A callback function allows a query to be executed asynchronously. Instead of freezing the browser while waiting for a response, the script submits the request to the server and continues running. When the response returns, the callback function is executed.&lt;/P&gt;&lt;P&gt;That difference is important.&lt;/P&gt;&lt;H3&gt;Without a callback&lt;/H3&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;Submit the query to the database.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server processes the query.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server builds the response.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The response returns to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional client-side work happens.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The user can finally interact with the page.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;H3&gt;With a callback&lt;/H3&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;Submit the query to the database.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&lt;A class="" href="https://www.servicenow.com/community/community-central-forum/bd-p/community-central-forum" target="_blank" rel="noopener"&gt;Community Central forum&lt;/A&gt;The user can keep interacting with the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server processes the query.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The server builds the response.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The response returns to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The callback function runs.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional client-side work happens inside the callback.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;That second flow is usually much better for performance.&lt;/P&gt;&lt;H3&gt;Example: asynchronous GlideRecord query&lt;/H3&gt;&lt;PRE&gt;var gr = new GlideRecord('a_table');
gr.addQuery('some', 'conditions');
gr.query(myCallBack);

// define the callback function
function myCallBack(gr) {
    while (gr.next()) {
        // do some client-side work
    }
}&lt;/PRE&gt;&lt;P&gt;The same idea applies to g_form.getReference():&lt;/P&gt;&lt;PRE&gt;g_form.getReference('assigned_to', cbFunc);

function cbFunc(gr) {
    var assignedToName = gr.getValue('name');
    alert('This ticket is assigned to: ' + assignedToName + '.');
}&lt;/PRE&gt;&lt;P&gt;In both cases, the browser stays responsive while the server does the heavier work.&lt;/P&gt;&lt;H2&gt;3) GlideAjax: The Server-Side Bridge for Client Scripts&lt;/H2&gt;&lt;P&gt;GlideAjax is one of the most useful but least understood APIs in ServiceNow because it has both a client-side part and a server-side part.&lt;/P&gt;&lt;P&gt;It is not simply a replacement for GlideRecord. Instead, it is a way to send a request from the browser to the server, run a Script Include there, and send data back to the client.&lt;/P&gt;&lt;P&gt;That makes GlideAjax especially useful when you need to:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;query data from the database,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;return a value to the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;avoid synchronous client-side database access,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;or return structured data back to the browser.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;The response from GlideAjax is XML, and that means it can hold more than one value.&lt;/P&gt;&lt;H2&gt;4) GlideAjax From the Client&lt;/H2&gt;&lt;P&gt;A basic GlideAjax call starts in the client script.&lt;/P&gt;&lt;H3&gt;Example: client-side GlideAjax&lt;/H3&gt;&lt;PRE&gt;var ga = new GlideAjax('AjaxScriptInclude'); // exact Script Include name
ga.addParam('sysparm_name', 'greetingFunction'); // function to run
ga.addParam('sysparm_my_name', 'Tim'); // optional parameter
ga.getXML(myCallBack); // callback for the response

function myCallBack(response) {
    var greeting = response.responseXML.documentElement.getAttribute('answer');
    alert(greeting);
}&lt;/PRE&gt;&lt;H3&gt;What each line does&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;new GlideAjax('AjaxScriptInclude') tells ServiceNow which Script Include to call.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;sysparm_name identifies the function inside the Script Include.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Additional parameters, such as sysparm_my_name, can be passed into the server-side function.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;getXML(myCallBack) sends the request and handles the result asynchronously.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;The response variable contains XML, and the returned value is usually available through the answer attribute:&lt;/P&gt;&lt;PRE&gt;var greeting = response.responseXML.documentElement.getAttribute('answer');&lt;/PRE&gt;&lt;P&gt;That is the standard pattern when the Script Include returns a single value.&lt;/P&gt;&lt;H2&gt;5) Building the GlideAjax Script Include&lt;/H2&gt;&lt;P&gt;To make GlideAjax work, the server-side Script Include must be client callable and must extend AbstractAjaxProcessor.&lt;/P&gt;&lt;H3&gt;Example: server-side Script Include&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        return 'Hiya, ' + userName + '.';
    }
});&lt;/PRE&gt;&lt;H3&gt;Important points&lt;/H3&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;The Script Include name must match the client-side name.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;sysparm_name tells ServiceNow which function to run.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;this.getParameter('sysparm_my_name') retrieves the parameter passed from the client.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;The function runs on the server, so you can use server-side APIs and database access there.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;6) Private Functions in GlideAjax Script Includes&lt;/H2&gt;&lt;P&gt;Not every function in a Script Include should be callable from the client. Sometimes you want helper logic that stays internal.&lt;/P&gt;&lt;P&gt;If the Script Include extends AbstractAjaxProcessor, a function name starting with an underscore is treated as private.&lt;/P&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        var msg = this._getMsg(userName);
        return msg;
    },

    _getMsg: function(userName) {
        return 'Hey there, ' + userName + '.';
    }
});&lt;/PRE&gt;&lt;P&gt;Here:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;greetingFunction() is the public function called by GlideAjax.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;_getMsg() is a private helper used only inside the Script Include.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This is a clean way to separate callable logic from internal utility logic.&lt;/P&gt;&lt;H2&gt;7) Returning Multiple Values from GlideAjax&lt;/H2&gt;&lt;P&gt;Since GlideAjax returns XML, one approach is to create additional XML nodes and attach attributes to them. This lets you return more than one value from the server.&lt;/P&gt;&lt;P&gt;The notes show an example returning greetings in English, French, and Spanish.&lt;/P&gt;&lt;H3&gt;Server-side example&lt;/H3&gt;&lt;PRE&gt;var AjaxScriptInclude = Class.create();
AjaxScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    greetingFunction: function() {
        var userName = this.getParameter('sysparm_my_name');
        this._getEnglishMsg(userName);
        this._getFrenchMsg(userName);
        this._getSpanishMsg(userName);
    },

    _getEnglishMsg: function(userName) {
        var greeting = 'Howdy, ' + userName + '. How are you?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'English');
        msg.setAttribute('value', greeting);
    },

    _getFrenchMsg: function(userName) {
        var greeting = 'Bonjour, ' + userName + '. Ça va?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'French');
        msg.setAttribute('value', greeting);
    },

    _getSpanishMsg: function(userName) {
        var greeting = 'Hola, ' + userName + '. Cómo estás?';
        var msg = this.newItem('greeting');
        msg.setAttribute('lang', 'Spanish');
        msg.setAttribute('value', greeting);
    }
});&lt;/PRE&gt;&lt;H3&gt;Client-side example&lt;/H3&gt;&lt;PRE&gt;var ga = new GlideAjax('AjaxScriptInclude');
ga.addParam('sysparm_name', 'greetingFunction');
ga.addParam('sysparm_my_name', 'Tim');
ga.getXML(myCallBack);

function myCallBack(response) {
    var language;
    var grtng;
    var greetings = response.responseXML.getElementsByTagName('greeting');

    for (var i = 0; i &amp;lt; greetings.length; i++) {
        language = greetings[i].getAttribute('lang');
        grtng = greetings[i].getAttribute('value');
        console.log(language + ': ' + grtng);
    }
}&lt;/PRE&gt;&lt;P&gt;This works, but it is often more complex than needed. A simpler modern pattern is to return an object as JSON and parse it on the client.&lt;/P&gt;&lt;H2&gt;&lt;span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"&gt;😎&lt;/span&gt; Why JSON Is Often the Better Option&lt;/H2&gt;&lt;P&gt;If you need to return multiple values, JSON is often easier to maintain than raw XML node handling. It gives you a structured payload that is more readable for developers and easier to expand later.&lt;/P&gt;&lt;P&gt;The basic pattern is:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;&lt;P&gt;build an object or array on the server,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;encode it as a JSON string,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;return it through GlideAjax,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;parse it on the client,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;use the values in the UI.&lt;/P&gt;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;The notes also mention that in scoped applications, JSON.stringify() and JSON.parse() should be used instead of older global-scope methods.&lt;/P&gt;&lt;H2&gt;9) Return a Simple Object Using JSON&lt;/H2&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleObject: function() {
        var obj = {};
        var sysId = this.getParameter('sysparm_sys_id');

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addQuery('sys_id', sysId);
        almAssetGr.query();

        if (almAssetGr.next()) {
            obj.model = almAssetGr.getDisplayValue('model');
            obj.model_category = almAssetGr.getDisplayValue('model_category');

            var json = new JSON();
            var data = json.encode(obj);
        }

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleObject');
    ga.addParam('sysparm_sys_id', g_form.getValue('sys_id'));
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);
    g_form.addInfoMessage('Asset Model: ' + answer.model);
    g_form.addInfoMessage('Asset Category: ' + answer.model_category);
}&lt;/PRE&gt;&lt;P&gt;This is a neat pattern when you want to send a small set of related fields back to the client.&lt;/P&gt;&lt;H2&gt;10) Return a Simple Array Using JSON&lt;/H2&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleArray: function() {
        var obj = [];
        var sysId = this.getParameter('sysparm_sys_id');

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addQuery('sys_id', sysId);
        almAssetGr.query();

        if (almAssetGr.next()) {
            obj[0] = almAssetGr.getDisplayValue('model');
            obj[1] = almAssetGr.getDisplayValue('model_category');

            var json = new JSON();
            var data = json.encode(obj);
        }

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleArray');
    ga.addParam('sysparm_sys_id', g_form.getValue('sys_id'));
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);

    for (var i = 0; i &amp;lt; answer.length; i++) {
        g_form.addInfoMessage(answer[i]);
    }
}&lt;/PRE&gt;&lt;P&gt;This is useful when the returned data is ordered rather than named.&lt;/P&gt;&lt;H2&gt;11) Return an Array of Objects Using JSON&lt;/H2&gt;&lt;P&gt;This is one of the most useful patterns when you need to send a list of structured rows to the client.&lt;/P&gt;&lt;H3&gt;Server-side code&lt;/H3&gt;&lt;PRE&gt;var AjaxUtils = Class.create();
AjaxUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    returnSimpleJSONObject: function() {
        var obj = [];
        var sysIds = '1bc1fa8837f3100044e0bfc8bcbe5d48,1fc1fa8837f3100044e0bfc8bcbe5d50,ffa96c0d3790200044e0bfc8bcbe5d87';

        var almAssetGr = new GlideRecord("alm_asset");
        almAssetGr.addEncodedQuery('sys_idIN' + sysIds);
        almAssetGr.query();

        while (almAssetGr.next()) {
            var payload = {};
            payload.model = almAssetGr.getDisplayValue('model');
            payload.model_category = almAssetGr.getDisplayValue('model_category');

            obj.push(payload);
        }

        var json = new JSON();
        var data = json.encode(obj);

        return data;
    },

    type: 'AjaxUtils'
});&lt;/PRE&gt;&lt;H3&gt;Client-side code&lt;/H3&gt;&lt;PRE&gt;function onLoad() {
    var ga = new GlideAjax('AjaxUtils');
    ga.addParam('sysparm_name', 'returnSimpleJSONObject');
    ga.getXML(showMessage);
}

function showMessage(response) {
    var answer = response.responseXML.documentElement.getAttribute("answer");
    g_form.addInfoMessage('JSON String: ' + answer);

    answer = JSON.parse(answer);

    for (var i = 0; i &amp;lt; answer.length; i++) {
        g_form.addInfoMessage(answer[i].model + " - " + answer[i].model_category);
    }
}&lt;/PRE&gt;&lt;P&gt;This is a practical pattern for returning row-style data such as assets, users, incidents, tasks, or catalog-related metadata.&lt;/P&gt;&lt;H2&gt;12) Reference Fields and Display Values&lt;/H2&gt;&lt;P&gt;A common problem in client scripts is setting a reference field value. A reference field query often triggers a synchronous server call, which can lock the browser briefly.&lt;/P&gt;&lt;P&gt;The notes point out a useful workaround: when setting a reference field, provide both the sys_id and the display value.&lt;/P&gt;&lt;PRE&gt;g_form.setValue('some_ref_field', varContainingSysID, 'The Display Value');&lt;/PRE&gt;&lt;P&gt;This helps the form avoid extra unnecessary work and gives the field a proper display label immediately.&lt;/P&gt;&lt;H2&gt;13) Client-Side Encoded Queries&lt;/H2&gt;&lt;P&gt;Another useful trick is that client-side GlideRecord does not support addEncodedQuery() the same way server-side GlideRecord does. However, if you call addQuery() with a single argument, that argument is treated as an encoded query.&lt;/P&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;var gr = new GlideRecord('table_name');
gr.addQuery('active=true^approval=approved^assigned_to=62826bf03710200044e0bfc8bcbe5df1');
gr.query();

while (gr.next()) {
    // do some work
}&lt;/PRE&gt;&lt;P&gt;This can be very helpful when you need to keep a client-side query compact, especially when the logic is too complex for separate chained conditions.&lt;/P&gt;&lt;H2&gt;14) GlideRecord and JavaScript Operators&lt;/H2&gt;&lt;P&gt;The addQuery() method can accept different styles of input:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;one argument: encoded query,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;two arguments: field and value,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;three arguments: field, operator, value.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H3&gt;Example&lt;/H3&gt;&lt;PRE&gt;gr.addQuery('number', 'STARTSWITH', 'INC');&lt;/PRE&gt;&lt;P&gt;Some commonly used operators include:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;gt;&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;lt;&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;gt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;&amp;lt;=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;!=&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;STARTSWITH&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;ENDSWITH&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;CONTAINS&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;DOES NOT CONTAIN&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;IN&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;INSTANCEOF&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Examples:&lt;/P&gt;&lt;PRE&gt;gr.addQuery('short_description', 'CONTAINS', 'Help');
gr.addQuery('sys_class_name', 'INSTANCEOF', 'task');&lt;/PRE&gt;&lt;P&gt;These operators make your queries much more expressive and precise.&lt;/P&gt;&lt;H2&gt;15) Best Practice Summary&lt;/H2&gt;&lt;P&gt;Here is the core guidance from this article in one place:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;Avoid synchronous client-side database work when possible.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use callback functions for asynchronous client-side queries.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use GlideAjax when a client script needs server-side data.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Keep server-side logic inside client-callable Script Includes.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use private helper methods inside Script Includes when logic should not be exposed.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Prefer JSON when returning structured or multiple values.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use display values when setting reference fields.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Use encoded queries carefully on the client.&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;Choose the right query operator for readable and efficient conditions.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;16) Final Thoughts&lt;/H2&gt;&lt;P&gt;GlideRecord, GlideAjax, and callback functions are not just separate APIs. They are pieces of a larger performance strategy.&lt;/P&gt;&lt;P&gt;If you think in terms of browser responsiveness, server responsibility, and data shape, the whole design becomes much cleaner:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;P&gt;let the browser stay light,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;let the server do the heavy lifting,&lt;/P&gt;&lt;/LI&gt;&lt;LI&gt;&lt;P&gt;and return only the data the client truly needs.&lt;/P&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;That approach will make your ServiceNow solutions faster, easier to maintain, and much more professional in real-world use.&lt;/P&gt;&lt;HR /&gt;&lt;P&gt;If you are building client-side functionality in ServiceNow, GlideAjax is usually the safest and cleanest bridge between the browser and the server. And when you need richer data, JSON is often the most maintainable way to return it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Feel Free To Follow Me on LinkedIn :&amp;nbsp;&lt;A href="https://www.linkedin.com/in/shaah/" target="_blank" rel="noopener"&gt;https://www.linkedin.com/in/shaah/&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 28 Jul 2026 03:43:03 GMT</pubDate>
      <guid>https://www.servicenow.com/community/community-central-forum/gliderecord-amp-glideajax-in-servicenow-client-side-vs-server/m-p/3579857#M7569</guid>
      <dc:creator>AL-Khalid</dc:creator>
      <dc:date>2026-07-28T03:43:03Z</dc:date>
    </item>
  </channel>
</rss>

