← Home
🔥0 DAY
0 XP
Interview Prep · Scripting

SCENARIO-BASED
SCRIPTING.

Senior ServiceNow interviews rarely ask you to define GlideRecord. They hand you a messy situation — bad data, retries, recursion, async side-effects — and watch how you reason. Below are four scenarios pulled from real interview loops, each with a working approach, runnable simulator output, and the pitfall that trips most candidates.

Tap a scenario to inspect the simulator trace. Want timed drills? Try the GlideRecord practice set.

  1. 1. Cross-table GlideRecord update

    When an Incident is closed, update the Priority on every related Problem record to '2 - High'. How would you script it?

    How to answer

    • Query problem records via the parent reference field, not by joining incident.
    • Use setWorkflow(false) only if you must suppress notifications — defend the choice.
    • Batch with autoSysFields(false) when bulk updating to keep audit clean.

    Reference script

    var pr = new GlideRecord('problem');
    pr.addQuery('parent_incident', current.sys_id);
    pr.query();
    while (pr.next()) {
      pr.priority = 2;
      pr.update();
    }

    Pitfall

    Calling current.update() inside an after-business-rule on incident triggers recursion. Run this as a fix script or async BR, never sync after-update on the same row.

  2. 2. Integration error handling (REST outbound)

    Your outbound REST message to a vendor randomly times out. Walk through how you'd make the script resilient.

    How to answer

    • Wrap execute() in try/catch — RESTMessageV2 throws on transport failures.
    • Inspect response.haveError() AND the HTTP status — 200 with an error body is common.
    • Retry with exponential backoff for 5xx and 429, fail fast for 4xx auth errors.
    • Log to a custom table, not gs.log — you need queryable failure history.

    Reference script

    try {
      var r = new sn_ws.RESTMessageV2('Vendor', 'sync');
      r.setHttpTimeout(15000);
      var resp = r.execute();
      var status = resp.getStatusCode();
      if (status >= 500 || status == 429) {
        scheduleRetry(current.sys_id);
      } else if (resp.haveError()) {
        logFailure(current, resp.getErrorMessage());
      } else {
        current.sync_state = 'ok';
        current.update();
      }
    } catch (e) {
      logFailure(current, e.message);
    }

    Pitfall

    Don't retry inside the same transaction — you'll hold a DB row lock for seconds. Push retries onto a scheduled job or event queue.

  3. 3. Business rule recursion

    A before-update business rule on sys_user updates the same record's manager field. Production fills with duplicate audit entries. What's happening?

    How to answer

    • before-BR on the SAME record should NEVER call current.update() — the framework saves the row for you.
    • Assigning current.field = value inside before-update is enough; .update() retriggers the rule chain.
    • If you must update a DIFFERENT row, do it in an after-BR or use setWorkflow(false) on a new GlideRecord.

    Reference script

    // WRONG — recurses
    (function(current) {
      current.manager = lookupManager(current.department);
      current.update(); // ⛔ remove this line
    })(current);

    Pitfall

    If you genuinely need to write to current in a before-BR conditionally, guard with a flag in g_scratchpad or use Business Rule Conditions to skip on recursion.

  4. 4. Async event-driven workflow

    Closing a Change should notify the assigned group, update CMDB CI 'last_change' field, and post to Slack. The user can't wait for Slack to respond. Design it.

    How to answer

    • Fire a custom event from an after-BR: gs.eventQueue('change.closed', current).
    • Script Action handles CMDB update (sync, fast, internal table).
    • Separate Script Action posts to Slack via RESTMessageV2 — failure here doesn't roll back the close.
    • Notification listens on the same event for the group email — no script needed.

    Reference script

    // Business Rule (after, update, state=Closed)
    gs.eventQueue('change.closed', current, current.assignment_group, '');
    
    // Script Action 1 — CMDB
    (function(event) {
      var ci = new GlideRecord('cmdb_ci');
      if (ci.get(event.parm1)) {
        ci.last_change = event.parm2;
        ci.update();
      }
    })(event);

    Pitfall

    Don't pass GlideRecord references in event parm fields — they get stringified. Pass sys_ids and re-query inside the script action.

Keep going

Pair this guide with the topic glossaries and timed practice sets to lock in the vocabulary interviewers expect.