Built something you're proud of? Tell the story. A quick G2 review of App Engine or Build Agent helps other developers see what's possible on ServiceNow. Share your experience.

Why is the client-side GlideRecord considered inefficient?

lauri457
Tera Sage

Can someone clarify to me why the client side gr api is considered inefficient? Is there something I am overlooking? To me the api seems like a good alternative to having countless simple script includes for some highly specific purpose. I keep reading this claim everywhere so it got me curious and I ran through this extremely scientific empiric study on the topic.

 

I created a script include to get all incident numbers

var ClientGr = Class.create();
ClientGr.prototype = Object.extendsObject(AbstractAjaxProcessor, {

	query: function () {
		var _ = new GlideRecordSecure("incident"), __ = [];
		_.query();
		while (_.next()) {
			__.push(_.getDisplayValue())
		}
		return __.toString();
	},

	type: 'ClientGr'
});

Before calling my script include with glideajax from the console i flushed system cache with cache.do and impersonated joe employee.

var a = new window.gsft_main.GlideAjax("ClientGr");
a.addParam("sysparm_name",
"query");
a.getXMLAnswer((r) => console.log(r))

4 seconds. Although it does get faster on consecutive tries, I'm assuming because of caching acls and the query etc.

glideajax.png

Then I flushed cache again, impersonated ol' joe and tried with gliderecord

var g = new window.gsft_main.GlideRecord("incident")
g.setLimit(9999) //theres a default cap of 500, there are way less incidents on my pdi
g.setDisplayFields(["number"]) //only get number field
g.query((r) => {
    while (r.next()) {
        console.log(r)
    }
})

These both return the same result set of 16 incidents but gr is quite a bit faster (I am aware of the limited scope of my testing). 

gliderecord.png

If I try this with admin priviledges gr returns faster from the server but i'm guessing loses because of the payload size and how tcp works.

 

I did notice that the portal gliderecord does not have setDisplayFields but the whole gr is just a wrapper for glideajax using sysparm_processor="AJAXGlideRecord" so it can be used directly. 

 

The gr api even supports dotwalking with the setDisplayFields method. So what am i missing?

2 REPLIES 2

SumanthDosapati
Mega Sage

@lauri457 

Client side GlideRecord works, but it is generally not recommended because of how it behaves at scale. The main reason is that it makes many network round‑trips instead of a single server call. Even though it uses AJAXGlideRecord under the hood, it sends seperate requests for .query() and each .next() call. With large result sets, this becomes very slow.

Key reasons:

  1. Multiple network calls
    GlideAjax executes a single server side script include and returns all data at once.
    Client side GlideRecord sends one request for the query and then one request per record as you iterate. This adds a lot of latancy.

    var gr = new GlideRecord('incident');
    gr.addQuery('active', true);
    gr.query();   // network trip
    
    gr.next();    // network trip
    gr.next();    // another trip
    gr.next();    // another trip

    Thinkk about real environments with:

    • thousands of rows
    • High latency
    • Portal widgets making multiple GR queries
    • Multiple concurrent users
  2. Heavier payloads
    Clientside GlideRecord returns extra metadata (field types, labels, display values, etc.).
    GlideAjax can return only the specific fields needed.

  3. Unpredictable performance at scale
    Your test with 16 records runs fast, but real environments often have hundreds or thousands of rows.
    Many .next() calls across a high‑latency network can make a client GR query take many seconds.

     
  4. Not recommended for production use
    ServiceNow documentation and community guidance recommend using GlideAjax + server side Script Includes for business logic.
    Client side GlideRecord exists mostly for legacy compatibility and simple use cases.

and AFAIK, ACL evaluations happens per each record via another network call incase of glideRecordSecure.

Also, in your test case, you used setDisplayFields which might be a probable reason it was fast.

 

In short:
Client-side GlideRecord may look fine in small tests, but it does not scale well because it performs many server trips, returns large payloads, and handles ACLs less efficiently. GlideAjax is the recommended pattern for performance, security, and predictability.

 

Accept the solution and mark as helpful if it does, to benefit future readers.
Regards,
Sumanth

Thanks for the answer.

 

  1. Have you tried the api and observed this? It only sends one request to the xmlhttp endpoint when you call the query method. In my example above I have around 3k records with acls restricting the returned amount to 16. The 1.75s and 4.20s transaction times are for the code snippets from my op, notice the next call in the loop.
  2. I'd say the most common use case for glideajax is to just retrieve a single record/value. I don't see much of a difference in performance for this use case. But I can see the benefit in not having to pollute script includes with single use case queries from a governance POV. For more complex scenarios glideajax is the obvious choice but I'd argue it is quite rare to simply query a batch of full records anyways so even if you are trying to query a larger set of data for a particular field or two then the client gr seems at the very least like a potential choice here.
  3. It does not work like this and anyways I am using the same table above for both scripts. I did not describe the data but there are around 3k incidents with joe seeing the 16
  4. I haven't seen much official guidance except not to use query synchronously. As for community guidance it is not very valuable if it is based on misconceptions like your point 1 for example. I understand that the setDisplayFields method is undocumented and the gr client api can only be used in global scope.

Not sure why it matters what gliderecordsecure does because the client gr enforces acls too. My question is about the claims about the inefficiency of it. 

I don't see why the api would be removed so I'd just like to see arguments against using this type of pattern.

var ga = new GlideAjax("AJAXGlideRecord");
ga.addParam("sysparm_type", "query");
ga.addParam("sysparm_name", "incident");
ga.addParam("sysparm_max_query", "2");
ga.addParam("sysparm_chars", "caller_id=6816f79cc0a8016401c5a33be04be441");
ga.addParam("sysparm_display_fields", "number");