[object Object]

A glide list field looks like the elegant choice. One field on the form, comma-separated references, no scrolling, no second tab. A related list looks heavier — a separate section, paginated, with its own toolbar. The aesthetic favors glide list. The performance does not, past a certain scale, and the scale is lower than most teams realize.

What each one actually is

A glide list is a field on the parent record that stores a comma-separated list of sys_ids referencing rows in another table. The platform renders the field as a multi-select with type-ahead. The reference list is stored inline on the parent row.

A related list is a separate query against a join table (or a child table with a reference back to the parent) that is rendered as its own paginated list section on the form. The join table is independent of the parent record’s storage.

The architectural difference matters: a glide list is one row; a related list is many rows linked by a query. The first feels lighter, until the list contents grow.

The break-even point

A glide list works well for memberships up to roughly 20 to 30 references. Beyond that:

  • The form payload grows linearly with the membership count — every reference must be resolved to a display value for rendering.
  • The type-ahead search performance degrades because the platform has to filter against an in-memory list.
  • The form save cost grows because the entire list must be re-validated and re-serialized on every save.
  • The reference-qualifier evaluation runs against the entire candidate population, then filters down — the qualifier does not get to short-circuit.

Past 50 references, glide list becomes noticeably slow on a desktop browser and unusably slow on a mobile workspace. Past 200 references, the form can take seconds to render.

A related list on the same data does not suffer these issues, because pagination defers most of the work to the moment the user actually expands a page.

A simple benchmark

Run this against your own tenant to find the break-even point in your environment. Cardinality of the referenced table and complexity of the reference qualifier both shift the curve.

// Background script — measure form payload size by membership count
function measurePayload(parentTable, listField, refTable, counts) {
    var rec = new GlideRecord(refTable);
    rec.setLimit(counts[counts.length - 1]);
    rec.query();
    var ids = [];
    while (rec.next()) ids.push(rec.sys_id.toString());

    var p = new GlideRecord(parentTable);
    p.initialize();
    p.short_description = 'benchmark';
    var sysId = p.insert();

    counts.forEach(function(n) {
        var slice = ids.slice(0, n);
        var pp = new GlideRecord(parentTable);
        pp.get(sysId);
        pp.setValue(listField, slice.join(','));
        var t = new GlideDateTime().getNumericValue();
        pp.update();
        var elapsed = new GlideDateTime().getNumericValue() - t;
        var payload = pp.getValue(listField).length;
        gs.info('n=' + n + ' update_ms=' + elapsed + ' payload_bytes=' + payload);
    });
}

measurePayload('incident', 'u_watch_list_extended', 'sys_user', [10, 50, 100, 250, 500]);

Plot the elapsed time against n. The shape is usually flat-ish below 30, then linear above. The right break-even for your tenant is where the curve becomes uncomfortable, not where some article said it should be.

When glide list is still right

Despite all of the above, glide list earns its keep when:

  • The membership is small and bounded by business rules (a watch list with at most 5 names; a tag list with at most 10 tags).
  • Inline editing matters more than scale (users add and remove in the form, do not navigate to a separate section).
  • The reference table is small enough that the type-ahead works well (a few hundred candidates, not millions).
  • The membership rarely changes after creation.

For these cases, the form-density win is real and the performance penalty never materializes.

Related list is the better choice when:

  • Membership can exceed 50 references in normal operation.
  • The relationship has its own metadata (added-by, added-on, role within the membership).
  • Users want to filter, sort, or export the membership.
  • The relationship is bidirectional in a meaningful way — both sides care about the link.

The “own metadata” case is decisive on its own. A glide list cannot carry per-link attributes; if you need them, you need a join table, and once you have a join table, related list is the natural rendering.

The hybrid pattern

For relationships that are usually small but occasionally large, consider a hybrid:

  • A glide list field that holds up to a configured maximum (e.g., 25 references).
  • A Business Rule that prevents the list from growing past the cap.
  • An overflow related list (separately maintained) for cases that need to exceed the cap.

This is not pretty, but it gives you the form-density win for the common case while preventing the worst-case performance cliff. Document the pattern clearly; otherwise the next admin will remove the cap “to be flexible” and you will lose the protection.

Reference qualifiers: where glide list silently dies

A reference qualifier on a glide list runs against the candidate population every time the type-ahead fires. If the qualifier is a simple table filter, the cost is bounded. If the qualifier is a script that runs a GlideRecord query, the cost compounds — every keystroke in the type-ahead can trigger the script.

// BAD — runs on every type-ahead keystroke
javascript: var gr = new GlideRecord('sys_user_grmember');
            gr.addQuery('group', current.assignment_group);
            gr.query();
            var ids = [];
            while (gr.next()) ids.push(gr.user.toString());
            'sys_idIN' + ids.join(',');

Replace this with a reference qualifier that filters declaratively against the user table, or precompute the eligible list and store it on a system property. A scripted qualifier on a glide list with high cardinality is a latency time bomb.

For the broader concern of reference qualifier performance, see our reference qualifier performance tuning piece.

Mobile workspace considerations

The mobile workspace and the agent workspace each render glide list and related list differently. On mobile, glide list with more than 10 entries is genuinely painful — the multi-select widget does not scale to a small screen. Related list on mobile paginates naturally and feels fine.

If a form needs to work well on mobile, default to related list unless the membership is provably small.

Storage and indexing implications

A glide list column is one column with a delimited string. It cannot be indexed in a way that supports efficient “find all records where this list contains X” queries. The platform handles such queries by string matching, which is not free.

A related list backed by a join table can be indexed properly. The join table gets indexes on both sides, and “find all records where X is in the list” is a fast indexed lookup.

If your queries against the membership matter as much as the display, related list wins on the query plan even when glide list might win on the rendering.

The form-load profiler

When in doubt, profile. ServiceNow’s transaction analysis shows you per-section render time. Open a record that has the glide list field, view the transaction log entry for the form load, and look at how much time was spent rendering the field. If it is more than 100ms, the field is slowing the form perceptibly. If it is more than 300ms, users are feeling it on every form open.

UI density choice

This is partly an aesthetic decision. Glide list on a tight form is elegant — one line, comma-separated, no scroll. Related list is denser visually — a section, a toolbar, rows. For executive-facing forms where the membership is small, glide list reads better. For practitioner forms where the membership is the point, related list is better and the density is not a problem because practitioners want the detail.

Be deliberate about which audience the form serves. Do not let an executive aesthetic poison a practitioner form.

Sometimes you start with a glide list and the membership outgrows the design. The migration is mechanical but has rough edges:

  1. Create the join table with parent reference, child reference, and any metadata fields you wish you had.
  2. Write a one-time script that reads the comma-separated values from each parent and writes a row per reference into the join table.
  3. Add the related list to the form. Keep the glide list field visible but read-only for one full release.
  4. Watch for forms or scripts that read the glide list field directly. Update them to read from the join.
  5. Hide the glide list field. Optionally drop the column after a further grace period.

The third and fourth steps are where lazy migrations leave technical debt. A glide list field that has been deprecated for a year but is still queried by an obscure scheduled job is a time bomb. Audit the references.

Schema visibility for downstream consumers

A glide list field exposes its contents as a comma-separated string to any consumer reading the parent record. A related list exposes the same data only when the consumer queries the join table. If your data warehouse or reporting integration consumes the parent record without joining anything, glide list “just works” while related list requires an extra query.

This is occasionally a reason to keep a glide list. Document the consumer constraint explicitly so the next admin understands why the glide list was preferred despite the cardinality.

Tradeoffs to be honest about

There is no universal winner. The right answer is per-relationship and depends on expected cardinality, query patterns, mobile usage, and metadata richness. The wrong choice is to pick one as a global convention and apply it everywhere.

When you are uncertain, default to related list. Its scaling is more graceful and its failure modes are less surprising.

Bottom line

  • Glide list works well under 30 references and degrades visibly above 50. Past 200, the form is slow enough to notice.
  • Related list pays for its visual density with predictable pagination behavior and indexable storage.
  • Scripted reference qualifiers on a glide list field are a common latency time bomb. Make qualifiers declarative or precompute.
  • Mobile workspace tilts the decision toward related list. Multi-select on small screens does not scale.
  • The right answer is per-relationship. If forced to a global default, default to related list.
[object Object]
Share