Ch. 15

ServiceNow interview questions & answers

ServiceNow admin and developer interviews: the platform and ITSM, tables and CMDB, business rules and client scripts, GlideRecord, Flow Designer, ACLs and integrations.

43 interview questions0 quiz questions0 notes
your progress0%

Top 43 ServiceNow interview questions most asked first

  1. 1.What is ServiceNow, and what do people mean by the Now Platform and its "single data model"?easy

    ServiceNow is a cloud platform for digital workflows. It started with IT Service Management, but today it runs HR, customer service, security operations, asset management and custom apps, all on one underlying platform, which ServiceNow markets as the Now Platform (recent docs call it the ServiceNow AI Platform).

    Every customer gets their own instance: a dedicated application and database stack reached at a URL like company.service-now.com. Typically you have separate dev, test and prod instances.

    The single data model means every app shares the same database, tables and services: users, groups, the CMDB, the Task table, workflows, notifications, reporting and security. So an incident, an HR case and a change can all point at the same user and the same CI, and one ACL model, one flow engine and one reporting engine work across all of them. That avoids integrating a dozen separate tools.

    What interviewers listen for
    • Cloud platform for digital workflows, ITSM and beyond
    • Each customer has dedicated instances (dev, test, prod)
    • All apps share one database and common services
    • Shared users, groups, CMDB and Task table across apps

    Likely follow-up: What instances would you expect in a typical landscape, and how do they get refreshed?

  2. 2.What are the types of business rules (before, after, async, display), and when would you use each?easy

    A business rule is a server-side script that runs when a record is displayed, inserted, updated, deleted or queried. The When field decides the timing:

    • before: after the user submits but before the database write. Use it to validate data or set fields on current; changes save automatically, no update() needed. Can abort with current.setAbortAction(true).
    • after: after the database write. Use it to update related records, such as child tasks, because the current record is already saved.
    • async: runs later, in the background, as a scheduled job. Use it for slow work like integrations or heavy recalculation, so the user isn't waiting. previous isn't available.
    • display: runs when a form is loaded, before it reaches the browser. Mainly used to fill g_scratchpad with server data for client scripts.

    There is also the Query operation, normally paired with before, which adds conditions to every query on the table, for example to hide records.

    What interviewers listen for
    • before: validate or modify current, saves automatically
    • after: update related records once current is saved
    • async: background work, no previous object
    • display: populate g_scratchpad for client scripts
    • before query rules restrict which rows are returned

    Likely follow-up: Why is current.update() in a business rule a bad idea? · Where do business rules sit in the order of execution relative to engines?

  3. 3.What types of client scripts are there, and what parameters does an onChange script receive?easy

    Client scripts run JavaScript in the browser on forms. There are four types:

    • onLoad: when the form first renders, before the user can type. Good for setting defaults or hiding fields.
    • onChange: when a specific field's value changes. It receives control, oldValue (the value when the record loaded), newValue, isLoading and isTemplate.
    • onSubmit: when the form is submitted. Return false to cancel the submission, typically after validation fails.
    • onCellEdit: the only type that runs in list editing. It gets sysIDs, table, oldValues, newValue and a callback; calling callback(false) stops the change.

    The isLoading guard matters because onChange also fires while the form loads. And client scripts are for user experience, not security: anything enforced only in the browser can be bypassed through lists, imports or APIs.

    function onChange(control, oldValue, newValue, isLoading, isTemplate) {
      if (isLoading || newValue === '') {
        return; // don't run while the form is loading or when cleared
      }
      if (newValue == '1') {
        g_form.setMandatory('work_notes', true);
        g_form.showFieldMsg('priority', 'P1: add work notes', 'info');
      }
    }
    What interviewers listen for
    • onLoad, onChange, onSubmit, onCellEdit
    • onChange gets control, oldValue, newValue, isLoading, isTemplate
    • onSubmit returns false to cancel
    • onCellEdit is the only one for list editing
    • Client scripts are UX, not security

    Likely follow-up: How would you stop the same logic from being bypassed through list editing?

  4. 4.What is the difference between a UI policy, a client script and a data policy? When would you choose each?mid
    • UI policy: client-side, mostly no-code. Based on a condition it makes fields mandatory, read-only or visible, and can reverse the actions when the condition is false. It can also run a script when true or false. First choice for simple form behaviour.
    • Client script: client-side JavaScript for anything a UI policy can't do: calling the server with GlideAjax, setting values, changing choice options, validating on submit.
    • Data policy: server-side enforcement of mandatory and read-only. It applies no matter how data arrives: forms, imports, web services. It can't hide fields.

    On load, client scripts run before UI policies, and when they conflict on mandatory or read-only, the UI policy generally wins. The key interview point: UI policies and client scripts only protect the form. If a rule must hold for imports, APIs and list edits too, use a data policy (a data policy can also be applied as a UI policy on the client), a business rule, or an ACL.

    What interviewers listen for
    • UI policy: no-code mandatory, read-only, visible on forms
    • Client script: custom logic, GlideAjax, values, options
    • Data policy: server-side, applies to all data sources
    • Data policies cannot hide fields
    • UI policies run after onLoad client scripts

    Likely follow-up: A field is mandatory via UI policy, but records arrive via REST without it. Why, and how do you fix it?

  5. 5.What is the difference between an incident and a problem, and where does a known error fit in?easy

    An incident is an unplanned interruption to a service, or a reduction in its quality. The goal of Incident Management is to restore service as quickly as possible, even with a workaround. Example: email is down for the sales team, so the service desk restarts the mail service.

    A problem is the cause, or potential cause, of one or more incidents. Problem Management looks for the root cause and a permanent fix, and it can be reactive (after repeated incidents) or proactive (spotting trends before users are hit).

    A known error is a problem whose root cause is understood and that has a documented workaround, often published to the knowledge base so the service desk can resolve related incidents faster. The permanent fix usually goes through Change Management.

    In ServiceNow, incidents link to a problem through the problem_id field, and a problem can raise a change request to deliver the fix.

    What interviewers listen for
    • Incident: restore service fast, workaround acceptable
    • Problem: underlying cause of one or more incidents
    • Known error: root cause known, workaround documented
    • Permanent fix is delivered through a change

    Likely follow-up: How is incident priority calculated in ServiceNow? · What is a major incident and how is it handled differently?

  6. 6.How do you query records with GlideRecord? Walk me through addQuery, addEncodedQuery, setLimit and get.easy

    GlideRecord is the server-side API for database operations. You create it for a table, add conditions, call query(), then iterate with next().

    • addQuery(field, value) or addQuery(field, operator, value) adds a condition; multiple calls are ANDed.
    • addEncodedQuery(string) takes the encoded query you can copy from a list filter, like active=true^priority=1. ^ is AND, ^OR is OR.
    • setLimit(n) caps the number of rows fetched, which is important for performance.
    • get(sys_id) or get(field, value) loads a single record and returns true if it was found, so always check the return value.

    Prefer getValue() for reading a field as a string and setValue() for writing. And test encoded queries carefully: an invalid field name is dropped from the query, which can silently return every record in the table.

    var inc = new GlideRecord('incident');
    inc.addQuery('active', true);
    inc.addQuery('priority', '<=', 2);
    inc.addEncodedQuery('assignment_groupISEMPTY');
    inc.orderByDesc('sys_created_on');
    inc.setLimit(10);
    inc.query();
    while (inc.next()) {
      gs.info(inc.getValue('number') + ' ' + inc.getDisplayValue('caller_id'));
    }
    
    var one = new GlideRecord('incident');
    if (one.get('number', 'INC0010001')) { gs.info(one.getUniqueValue()); }
    What interviewers listen for
    • Create, add conditions, query(), loop with next()
    • addQuery supports an operator as the middle argument
    • addEncodedQuery takes list-filter syntax (^, ^OR)
    • setLimit caps rows; get() returns a boolean
    • Invalid query parts are dropped, not rejected

    Likely follow-up: How would you express an OR condition without an encoded query? · What is the difference between getValue() and dot-walking gr.field?

  7. 7.How do you call server-side code from a client script? Show a GlideAjax call and the matching script include.mid

    The standard way is GlideAjax calling a client-callable script include.

    On the server, the script include extends AbstractAjaxProcessor, its name matches the class name, and the Client callable (Glide AJAX enabled) box is checked. Methods read inputs with this.getParameter() and return a value.

    On the client, you create new GlideAjax('ClassName'), set sysparm_name to the method name, add your own parameters (they must start with sysparm_), and send it asynchronously. getXMLAnswer() hands the callback the answer string directly; getXML() gives you the XML response to parse.

    Avoid getXMLWait(): it's synchronous, freezes the browser and isn't available in scoped apps. Methods whose names start with an underscore aren't callable from the client, and recent releases protect client-callable script includes with ACLs, so check access when a call silently returns nothing.

    // Client script
    var ga = new GlideAjax('UserUtilsAjax');
    ga.addParam('sysparm_name', 'getDepartment');
    ga.addParam('sysparm_user', g_form.getValue('caller_id'));
    ga.getXMLAnswer(function (answer) {
      g_form.setValue('u_department', answer);
    });
    
    // Script include "UserUtilsAjax", Client callable checked
    var UserUtilsAjax = Class.create();
    UserUtilsAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {
      getDepartment: function () {
        var user = new GlideRecord('sys_user');
        return user.get(this.getParameter('sysparm_user')) ? user.getValue('department') : '';
      },
      type: 'UserUtilsAjax'
    });
    What interviewers listen for
    • Script include extends AbstractAjaxProcessor, Client callable
    • sysparm_name selects the method; params start with sysparm_
    • Use async getXML or getXMLAnswer with a callback
    • Avoid getXMLWait: blocks the browser, not in scoped apps
    • Underscore-prefixed methods are private

    Likely follow-up: When would you use a display business rule with g_scratchpad instead of GlideAjax?

  8. 8.What are current and previous in a business rule, and when is previous not available?easy

    current is a GlideRecord holding the record being processed, including the values the user just submitted. In a before rule you change it directly and the changes are saved automatically.

    previous holds the record as it was before this update, so you can compare old and new values. The GlideElement helpers changes(), changesFrom() and changesTo() use it under the hood, e.g. current.state.changesTo(6).

    previous is only meaningful on update and delete. It's not available in async business rules, because they run later as a scheduled job after the transaction has finished; that's why the default template says previous /*null when async*/, and why changes() doesn't work inside an async script. You can still use change conditions in the async rule's condition builder, because that's evaluated during the original transaction.

    (function executeRule(current, previous /*null when async*/) {
      if (current.state.changesTo(6)) { // 6 = Resolved on incident
        current.resolved_by = gs.getUserID();
      }
      if (previous && previous.getValue('priority') != current.getValue('priority')) {
        gs.info('Priority changed on ' + current.getValue('number'));
      }
    })(current, previous);
    What interviewers listen for
    • current: record with the new, submitted values
    • previous: values before this update
    • changes(), changesFrom(), changesTo() compare them
    • previous is null in async rules
    • Async rules can still use change conditions in the filter
  9. 9.How are ACLs evaluated in ServiceNow? Explain table versus field ACLs and the order of matching.mid

    To access a record, a user must pass both the table-level ACL and the field-level ACL for the operation (read, write, create, delete).

    Table ACLs match from most specific to most general: the table (incident), then its parent (task), then *.

    Field ACLs, per the docs: incident.number, task.number, *.number, then incident.*, task.*, *.*.

    The first matching ACL the user passes grants access and stops processing at that level; if the user passes none of the matching ACLs, access is denied. If several ACLs match at the same point in the order, passing any one is enough. Within a single ACL, the user must meet all of its requirements: one of the required roles, the data condition and the script (answer = true).

    Recent releases add Deny-Unless ACLs, which are evaluated before the normal Allow-If ones: fail a Deny-Unless and you're denied, whatever the Allow-If rules say. Admins can view and debug ACLs, but creating or editing them requires elevating to security_admin. The security debug output shows which rule passed or failed.

    What interviewers listen for
    • Must pass table-level and field-level ACLs
    • Specific to general: table, parent, then *
    • Any one passing ACL at the same point is enough
    • Within an ACL: role AND condition AND script
    • Deny-Unless ACLs evaluated before Allow-If

    Likely follow-up: A user with the right role still can't see a field. How do you debug it?

  10. 10.What is an update set, and how do you move one from dev to test to production?easy

    An update set is a named group of configuration changes (customer updates in sys_update_xml) that you move between instances as a unit.

    The flow:

    • In dev, create an update set and make it current, then build. Each change to a tracked record is captured; multiple edits to the same record keep only the latest version.
    • Mark it Complete.
    • In the target instance, retrieve it, either from a remote update source or by importing the exported XML.
    • Preview it. The preview flags problems such as collisions with newer local changes or missing referenced records. You resolve each one by accepting or skipping the remote update.
    • Commit it.

    Good habits: never build in the Default update set, keep sets small and focused, preview in test before prod, and use batching (parent/child sets) for large releases. Update sets are per application scope, so scoped app changes go into that app's update set.

    What interviewers listen for
    • Captures configuration, not data, in sys_update_xml
    • Complete, retrieve, preview, commit
    • Preview catches collisions and missing references
    • Only the latest version of each record is kept
    • Update sets are application-scope specific

    Likely follow-up: What isn't captured in an update set? · How would you back out an update set?

  11. 11.What are the three change types in ServiceNow, and what role does the CAB play?easy

    ServiceNow follows the ITIL change types:

    • Standard: pre-authorized, low risk, repeatable, with a proven history. Requested from a catalog of standard change templates. No peer approval or CAB step; it goes from New straight to Scheduled.
    • Normal: anything that isn't standard or emergency. It goes through the full lifecycle: New, Assess, Authorize, Scheduled, Implement, Review, Closed, with technical or peer approval and CAB authorization.
    • Emergency: must be done as soon as possible, for example to fix a major incident or apply an urgent security patch. It skips Assess and goes straight to Authorize, where the emergency CAB approves it quickly.

    The Change Advisory Board is the group that reviews and authorizes changes, weighing risk, impact, schedule conflicts and blackout windows. ServiceNow supports it with CAB meetings, agendas and the CAB Workbench. Good practice is to push more low-risk work into standard changes so the CAB spends time on genuinely risky ones.

    What interviewers listen for
    • Standard: pre-approved template, no CAB
    • Normal: full assessment and CAB authorization
    • Emergency: urgent, skips Assess, fast CAB approval
    • CAB weighs risk, impact and scheduling conflicts

    Likely follow-up: How would you decide that a change should become a standard change?

  12. 12.What is a script include, what kinds are there, and why prefer one over a global business rule?mid

    A script include is a reusable server-side library: a class or function you call from business rules, flows, UI actions, other script includes or, if client callable, from the browser via GlideAjax.

    The common shapes:

    • Class-based: Class.create() with a prototype, an initialize constructor and a type property. Called with new IncidentUtils().countOpenForCaller(id).
    • Classless (on-demand): a single function whose name matches the script include name.
    • Extending: Object.extendsObject(Parent, {...}), most often extending AbstractAjaxProcessor for GlideAjax.

    The name must match the class or function name. Accessible from controls whether other scopes may call it, and callers from another scope use the scope prefix, like new global.IncidentUtils().

    They beat global business rules because script includes load only when called, while global business rules load on every transaction. They're also easier to test and reuse.

    var IncidentUtils = Class.create();
    IncidentUtils.prototype = {
      initialize: function () {},
    
      countOpenForCaller: function (callerId) {
        var ga = new GlideAggregate('incident');
        ga.addQuery('caller_id', callerId);
        ga.addActiveQuery();
        ga.addAggregate('COUNT');
        ga.query();
        return ga.next() ? parseInt(ga.getAggregate('COUNT'), 10) : 0;
      },
    
      type: 'IncidentUtils'
    };
    What interviewers listen for
    • Reusable server-side class or function
    • Class-based, classless, or extending another class
    • Name must match the class or function
    • Loaded on demand, unlike global business rules
    • Accessible from controls cross-scope use

    Likely follow-up: How do you call a scoped script include from another scope?

  13. 13.What are g_form and g_user? Name the methods you use most often.easy

    Both are client-side globals available in form scripts.

    g_form (GlideForm) controls the current form:

    • getValue and setValue; pass the display value as the third argument of setValue for reference fields to save a server round trip
    • setMandatory, setReadOnly, setDisplay (removes the space) versus setVisible (leaves a gap)
    • showFieldMsg / hideFieldMsg, addInfoMessage / addErrorMessage
    • addOption, removeOption, clearOptions for choice lists
    • isNewRecord, getUniqueValue, getTableName, save, submit

    g_user (GlideUser) describes the logged-in user: userID, userName, firstName, lastName, getFullName(), hasRole(), hasRoleExactly() and hasRoleFromList().

    Watch out: g_user.hasRole('itil') also returns true for admins, while hasRoleExactly() doesn't. And checking roles in the browser is for UX only; real enforcement is ACLs.

    function onLoad() {
      if (!g_user.hasRole('itil')) {
        g_form.setReadOnly('assignment_group', true);
        g_form.setDisplay('work_notes', false);
      }
      if (g_form.isNewRecord()) {
        g_form.setValue('caller_id', g_user.userID, g_user.getFullName());
        g_form.addInfoMessage('Hi ' + g_user.firstName + ', describe the issue.');
      }
    }
    What interviewers listen for
    • g_form manipulates the form, g_user describes the user
    • setDisplay removes space; setVisible leaves a gap
    • setValue with display value avoids a server call
    • hasRole returns true for admin; hasRoleExactly does not
    • Client-side role checks are UX, not security
  14. 14.A client script needs data that isn't on the form. What are your options, and which is most efficient?mid

    There are four ways to get server data into the browser:

    • Display business rule + g_scratchpad: the rule runs when the form is built and puts values into g_scratchpad, which ships with the form. No extra round trip, so it's the most efficient choice when you know what you need at load time.
    • Asynchronous GlideAjax: calls a client-callable script include on demand, for example in an onChange. Best when the data depends on what the user just picked.
    • g_form.getReference(field, callback): fetches the whole referenced record. Easy, but it pulls every field; the docs no longer recommend it.
    • Client-side GlideRecord: also not recommended, for the same performance reasons.

    A related anti-pattern is adding a field to the form only to hide it so a script can read it. It works, but it's slower than a scratchpad value. So: scratchpad for load-time data, async GlideAjax for dynamic data, and never a synchronous call.

    // Display business rule on incident
    (function executeRule(current, previous) {
      g_scratchpad.isVip = current.caller_id.vip == true;
      g_scratchpad.managerName = current.caller_id.manager.getDisplayValue();
    })(current, previous);
    
    // onLoad client script
    function onLoad() {
      if (g_scratchpad.isVip) {
        g_form.addInfoMessage('VIP caller. Manager: ' + g_scratchpad.managerName);
      }
    }
    What interviewers listen for
    • Display rule fills g_scratchpad, sent with the form
    • Scratchpad only works for load-time data
    • Async GlideAjax for data that depends on user input
    • getReference and client GlideRecord fetch whole records
    • Avoid synchronous calls and hidden helper fields
  15. 15.How would you count records efficiently? Compare getRowCount() with GlideAggregate.mid

    getRowCount() is a GlideRecord method: you run a normal query, which retrieves the matching records, and then ask how many came back. That's fine if you're going to loop over the records anyway, but wasteful if all you need is the number.

    GlideAggregate extends GlideRecord and pushes the aggregation to the database: COUNT, SUM, MIN, MAX, AVG and a few others. You add the aggregate before query(), then read it with getAggregate(). Pass a field name, or call groupBy(), to get one row per group, like a SQL GROUP BY. addHaving() filters on the aggregate, and orderByAggregate() sorts by it.

    So the rule of thumb from the docs: if you only need a count, use GlideAggregate; use getRowCount() only when you also need the records. Note that getAggregate() returns a string, so convert it before doing arithmetic.

    // Count active incidents per category
    var ga = new GlideAggregate('incident');
    ga.addActiveQuery();
    ga.addAggregate('COUNT', 'category');
    ga.orderByAggregate('COUNT', 'category');
    ga.query();
    while (ga.next()) {
      gs.info(ga.getValue('category') + ': ' + ga.getAggregate('COUNT', 'category'));
    }
    What interviewers listen for
    • getRowCount retrieves the records, then counts
    • GlideAggregate counts in the database
    • Add the aggregate before query()
    • groupBy or a field argument gives per-group rows
    • getAggregate returns a string
  16. 16.What is not captured by update sets, and how do you move those things between instances?mid

    Update sets track configuration on tables that have the update_synch attribute: forms, fields, business rules, client scripts, ACLs, catalog item definitions and so on. Things that commonly catch people out:

    • Data: incidents, requests, submitted catalog orders, CIs, users, group memberships and role grants. These are data, not configuration.
    • Home pages and content pages: not added by default; you have to unload them into the current update set.
    • Table deletions: removing a table isn't tracked, so you delete it manually on the target.
    • Data-losing dictionary changes: a type change that would lose data is skipped on commit and logged.
    • Changes made in another scope or another update set, which is why picking the right current update set matters.

    To move data, use Export XML / Import XML for a few records (keeps sys_ids), or import sets, including instance-to-instance imports, for larger volumes. Don't add the update_synch attribute yourself: the docs warn it can cause serious performance problems.

    What interviewers listen for
    • Only tables with update_synch are tracked
    • Transactional data, users and memberships are not
    • Home pages must be unloaded manually
    • Table deletions are not tracked
    • Move data with XML export/import or import sets
  17. 17.How do tables, the dictionary and table extension work in ServiceNow? Why is the Task table important?easy

    Tables are defined in sys_db_object and their columns in the dictionary, sys_dictionary, which stores each field's type, length, default value, reference target and attributes. Every record has system fields like sys_id (a 32-character GUID), sys_created_on and sys_updated_by.

    A table can extend another, and only at creation time. The child inherits all the parent's fields and adds its own; sys_class_name tells you which class a record belongs to. Custom global tables and fields get a u_ prefix; scoped ones get the app's x_ prefix.

    Task is the key base table. Incident, Problem, Change Request, Requested Item, Catalog Task and many others extend it, so they share fields like number, state, assignment group, assigned to, priority, work notes and comments, plus features built on Task: approvals, SLAs, assignment rules and the activity stream. That's why you extend Task for any new work-tracking app.

    When a child needs different behaviour for an inherited field, such as a different default or reference qualifier, you use a dictionary override rather than changing the parent.

    What interviewers listen for
    • sys_db_object holds tables, sys_dictionary holds fields
    • Child tables inherit parent fields; sys_class_name identifies class
    • Extension is chosen when the table is created
    • Task gives SLAs, approvals, assignment, activity stream
    • Dictionary overrides change inherited fields per child

    Likely follow-up: What would you gain by extending Task for a new custom app?

  18. 18.What is a reference field, and what is dot-walking? Where can and can't you dot-walk?easy

    A reference field stores the sys_id of a record in another table, like a foreign key, and shows that record's display value. caller_id on Incident references sys_user.

    Dot-walking follows references with dots to reach fields on related records: current.caller_id.manager.email. You can use it:

    • in server scripts (business rules, script includes)
    • in condition builders and filters, by expanding related fields
    • in list and form layouts, to show related-record fields
    • in encoded queries, like caller_id.vip=true

    On the client you can't dot-walk with g_form: g_form.getValue('caller_id') only gives you the sys_id. Use a display rule with g_scratchpad, GlideAjax, or, less ideally, g_form.getReference().

    Two tips: dot-walked values are GlideElement objects, so call toString() or getDisplayValue() when you need a string; and each hop can mean another database lookup, so avoid long dot-walks inside big loops.

    var inc = new GlideRecord('incident');
    if (inc.get('number', 'INC0010001')) {
      gs.info(inc.caller_id.getDisplayValue());        // caller's name
      gs.info(inc.caller_id.manager.email.toString()); // dot-walk two levels
      var caller = inc.caller_id.getRefRecord();       // full sys_user GlideRecord
      gs.info(caller.getValue('department'));
    }
    What interviewers listen for
    • Reference field stores a sys_id of another record
    • Dot-walking follows references: caller_id.manager.email
    • Works in scripts, filters, layouts, encoded queries
    • No dot-walking through g_form on the client
    • Each hop may cost a query; watch loops
  19. 19.Explain how import sets, transform maps and coalesce work. How do you stop duplicates being created?mid

    An import has three parts:

    • A data source (file, JDBC, LDAP, REST and others) loads rows into an import set staging table.
    • A transform map maps staging fields to a target table, such as sys_user or cmdb_ci_server, through field maps and optional scripts.
    • The transform writes each row to the target and records the outcome (inserted, updated, ignored, error) in the import log.

    Coalesce decides insert versus update. Mark one or more field maps as coalesce: if a target record matches on all coalesce fields, it's updated; if not, a new record is inserted. With no coalesce, every row is inserted, which is the classic cause of duplicates. Coalesce on fields that are genuinely unique, like email or employee number; if several target records match, only the first is updated.

    For custom logic, transform event scripts run at onStart, onBefore, onAfter and onComplete, among others, with source, target, map, log and action. Setting ignore = true in onBefore skips that row.

    // onBefore transform script: update existing records only
    (function runTransformScript(source, map, log, target) {
      if (action == 'insert') {
        ignore = true; // skip rows with no coalesce match
        log.info('Skipped unmatched row: ' + source.u_email);
      }
    })(source, map, log, target);
    What interviewers listen for
    • Data source to staging table to transform map
    • Coalesce match updates; no match inserts
    • Multiple coalesce fields must all match
    • No coalesce means every row is inserted
    • Transform scripts: onStart, onBefore, onAfter, onComplete

    Likely follow-up: How would you coalesce on email OR username? · What does "Run business rules" on a transform map control?

  20. 20.What is the difference between Flow Designer and the legacy Workflow editor? Which would you use for new work?mid

    Flow Designer is ServiceNow's low-code automation tool; in recent releases it lives inside Workflow Studio. A flow has a trigger and a series of actions:

    • Triggers: record created or updated, scheduled (daily, weekly, run once, repeat), or application triggers such as Service Catalog, SLA Task and inbound email.
    • Actions: reusable building blocks with defined inputs and outputs, from core ones like Create Record and Ask for Approval to spoke actions for third-party systems through IntegrationHub.
    • Subflows: reusable sequences you call from other flows.
    • Flow logic: If, For Each, Do Until, Wait and so on, with data pills passing values between steps.

    The legacy Workflow editor is the older drag-and-drop canvas of activities and transitions, attached to a table. It still runs in many instances, and you'll maintain existing workflows, but the docs now point to Workflow Studio for new process automation, and even suggest it over business rules. Flows are easier to read, reuse and upgrade, and the execution details page makes debugging much simpler.

    What interviewers listen for
    • Flows: trigger plus actions, subflows and flow logic
    • Reusable actions with inputs, outputs and data pills
    • Spokes add third-party actions via IntegrationHub
    • Legacy workflows: maintain, but build new in flows
    • Execution details make flows easier to debug

    Likely follow-up: When would you still write a business rule instead of a flow?

  21. 21.What is a UI action, and how do you make one that runs client-side validation and then server-side code?mid

    A UI action adds a button, link or menu item to forms and lists: form button, form context menu, form link, list button, list choice, list context menu and so on. It has a Condition (evaluated on the server) and optional required roles that control when it appears, and a script that runs when it's clicked.

    By default the script runs on the server, with current available; action.setRedirectURL() controls where the user lands. With the Client box checked, the Onclick field names a function that runs in the browser with g_form available.

    To do both, use the classic pattern from base-system actions: the client function validates, then calls gsftSubmit(null, g_form.getFormElement(), '<action name>') to submit the form back to the server with that action name. On the server there is no window object, so a typeof window == 'undefined' check calls the server function. The Action name must match the one passed to gsftSubmit. Workspaces use a separate Workspace client script.

    // UI action: Client = true, Onclick = resolveClient(), Action name = resolve_inc
    function resolveClient() {
      if (!g_form.getValue('close_notes')) {
        g_form.showFieldMsg('close_notes', 'Close notes are required', 'error');
        return false;
      }
      gsftSubmit(null, g_form.getFormElement(), 'resolve_inc'); // re-submit to server
    }
    
    if (typeof window == 'undefined') resolveServer();
    
    function resolveServer() {
      current.state = 6;
      current.update();
      action.setRedirectURL(current);
    }
    What interviewers listen for
    • Buttons, links and menu items on forms and lists
    • Server-side condition and roles control visibility
    • Client checkbox plus Onclick runs browser code
    • gsftSubmit re-submits using the Action name
    • typeof window check runs the server part
  22. 22.What is the CMDB? Explain CIs, CI classes and relationships.easy

    The Configuration Management Database stores the things you manage, configuration items (CIs), and how they relate, so you can understand the impact of an incident or change.

    • CI classes form a table hierarchy under cmdb_ci: for example cmdb_ci_hardware extends to cmdb_ci_computer, which extends to cmdb_ci_server and then to cmdb_ci_linux_server. Application and service classes sit alongside them. The CI Class Manager is where you view and extend the hierarchy.
    • Relationships live in cmdb_rel_ci, each with a parent, a child and a type such as Depends on::Used by or Runs on::Runs. They let you trace from a business service down to the servers it relies on.
    • Population: Discovery, Service Mapping and Service Graph Connectors fill the CMDB automatically; the Identification and Reconciliation Engine (IRE) uses identification rules to avoid duplicate CIs and reconciliation rules to decide which data source may update which attributes.

    A healthy CMDB is what makes impact analysis, change risk and event correlation trustworthy, and CMDB Health dashboards track completeness, correctness and compliance.

    What interviewers listen for
    • CIs and their relationships, stored under cmdb_ci
    • Class hierarchy, e.g. computer to server to linux server
    • Relationships in cmdb_rel_ci with typed parent/child
    • Discovery and connectors populate; IRE prevents duplicates
    • Enables impact analysis for incidents and changes

    Likely follow-up: What is CSDM and why does it matter?

  23. 23.When a user orders from the Service Catalog, which records get created? Explain REQ, RITM and SCTASK.easy

    Submitting a cart creates a three-level structure:

    • Request (sc_request, numbered REQ...): the overall order, like a shopping-cart receipt. It holds who requested it, for whom, and the overall approval and state.
    • Requested Item (sc_req_item, RITM...): one per catalog item in the order. Each RITM carries the variable answers the user filled in and runs that item's fulfillment process, a flow or a legacy workflow.
    • Catalog Task (sc_task, SCTASK...): the actual work assigned to fulfillment groups, created by the RITM's flow. One RITM can have several tasks, in sequence or in parallel.

    All three extend Task, so they get assignment, SLAs, approvals and the activity stream. On the server, you read variables from the RITM with current.variables.<variable_name>. Interviewers like to ask where approvals sit: typically on the RITM for item-specific approval (for example the user's manager), sometimes on the REQ for the whole order.

    What interviewers listen for
    • REQ: the whole order
    • RITM: one per item, holds variables, runs fulfillment
    • SCTASK: work assigned to fulfillment groups
    • All three extend the Task table
    • Read variables via current.variables.name
  24. 24.What are catalog items, variables and variable sets? When would you use a multi-row variable set?easy

    A catalog item is something users can order from the Service Catalog, like a laptop or software access. It has a name, description, category, pricing, a fulfillment flow and, most importantly, variables: the questions shown on the order form, such as select boxes, reference fields, checkboxes or dates.

    A variable set is a reusable group of variables you attach to many items. The classic example is a "Requested for" block used by dozens of items; change it once and every item picks up the change.

    Variable sets come in two kinds:

    • Single-row: an ordinary group of questions answered once.
    • Multi-row (MRVS): a grid where the user adds several rows, for example one row per new starter or per server. Its value is stored as JSON, so scripts parse it.

    Behaviour on the order form comes from catalog client scripts and catalog UI policies, which work like their form counterparts but target variables. They can be defined on an item or on a variable set.

    What interviewers listen for
    • Catalog item: orderable offering with variables
    • Variables are the order-form questions
    • Variable sets make groups of variables reusable
    • Multi-row variable set: grid, stored as JSON
    • Catalog client scripts and UI policies act on variables
  25. 25.What is a record producer, and how is it different from a regular catalog item?mid

    A record producer is a special catalog item that creates a record in a target table, typically a task table like Incident or an HR case, instead of a Request and Requested Item. It gives end users a friendly catalog-style form while producing a normal record behind it.

    Ways to populate the target record:

    • Name a variable the same as a target field, like caller_id, and it maps automatically.
    • Use a template for static values.
    • Use the script: current is the record being created and producer holds the user's answers, e.g. producer.issue_type.
    • Redirect afterwards with producer.redirect in the platform UI or producer.portal_redirect in Service Portal.

    Don't call current.update() or setAbortAction() in the script; the platform inserts the record for you. And the docs say not to use record producers to create Requested Items: if the user is ordering something that needs fulfillment, use a real catalog item so the request process runs.

    // Record producer script (target table: incident)
    current.short_description = 'Laptop issue: ' + producer.issue_type.getDisplayValue();
    current.urgency = producer.is_blocking == 'true' ? 1 : 3;
    current.assignment_group.setDisplayValue('Service Desk');
    producer.portal_redirect = 'sp?id=ticket&table=incident&sys_id=' + current.sys_id;
    What interviewers listen for
    • Creates a record in a target table, not REQ/RITM
    • Matching variable names map to fields
    • Script uses current and producer
    • producer.redirect / portal_redirect after submit
    • Do not call current.update() in the script
  26. 26.What is an order guide, and how does it decide which items to order?mid

    An order guide lets a user fill in one form and submit a single request that generates several requested items. The standard example is new-hire onboarding: enter the starter's department, location and role once, and the guide orders a laptop, phone, badge and software access.

    How it works:

    • The order guide has its own variables, the initial questions.
    • Rule base entries each say "if these conditions on the answers are true, include this catalog item".
    • Cascading variables: answers given in the guide can flow down to variables with the same name on the included items, so users don't re-enter them.
    • The user reviews the chosen items, fills in item-specific questions and submits once.

    A script field can also add or remove items with guide.add() and guide.remove(). Order guides can even run automatically from a flow or server script, without the user submitting, which suits HR-driven onboarding. The trade-off versus one big catalog item is that each item keeps its own fulfillment process.

    What interviewers listen for
    • One form, one request, several requested items
    • Rule base conditions decide which items are included
    • Cascading variables pass answers to items
    • Each item keeps its own fulfillment flow
    • Can be run automatically from a flow or script
  27. 27.What is the difference between a scoped application and the global scope? Why build scoped apps?mid

    A scoped application gets its own namespace, like x_acme_book_rooms (x_, the instance's company code, then the app ID). Its tables, script includes and other files carry that prefix, and the platform restricts what other scopes can touch.

    Protections you can configure:

    • Table application access: whether other scopes can read, create, update or delete the table, and whether it's reachable from web services.
    • Accessible from on script includes: this scope only, or all scopes.
    • Cross-scope privileges and runtime access tracking (None, Tracking or Enforcing) control what the app's scripts may do outside its scope.
    • Scoped scripts get the scoped API set: for example gs.info() instead of gs.log(), and no getXMLWait().

    Global is the legacy shared space where most base-system ITSM configuration lives; global code can reach almost anything, which is exactly the risk. Scoped apps give isolation, clearer ownership, safer upgrades and clean packaging through source control or the app repository, and new scoped apps default to the ES2021 JavaScript mode.

    What interviewers listen for
    • Scoped apps get an x_company_app namespace
    • Table access and Accessible from limit other scopes
    • Cross-scope privileges and runtime access tracking
    • Scoped APIs: gs.info, not gs.log
    • Isolation, ownership, easier upgrades and packaging

    Likely follow-up: How do you call a global script include from a scoped app?

  28. 28.How would an external system create or read incidents through REST, and when would you build a Scripted REST API instead?mid

    The out-of-box option is the Table API: /api/now/table/{tableName}. GET lists or reads a record by sys_id, POST creates, PUT or PATCH updates, DELETE deletes. Useful parameters include sysparm_query (an encoded query), sysparm_fields, sysparm_limit, sysparm_offset and sysparm_display_value. The REST API Explorer lets you try calls and generates sample code. Requests run as the authenticated user, so ACLs and data policies apply.

    For inbound data that needs mapping or validation, the Import Set API posts rows into a staging table so a transform map handles coalescing.

    Build a Scripted REST API when you want a clean contract that doesn't expose your table structure: combining several tables, business validation, custom status codes, or versioning. It lives at /api/<namespace>/<version>/<api_id>/<relative_path>, each resource has a script that receives request and response, and you can require ACLs on the API or individual resources.

    What interviewers listen for
    • Table API: /api/now/table/{table} with CRUD verbs
    • sysparm_query, sysparm_fields, sysparm_limit parameters
    • Import Set API when data needs transform and coalesce
    • Scripted REST API for custom contracts and logic
    • Calls run as the user, so ACLs apply
  29. 29.Write the script for a Scripted REST API POST resource that creates an incident. What do request and response give you?mid

    Each resource script is an IIFE receiving a RESTAPIRequest and a RESTAPIResponse.

    From request you get:

    • request.body.data: the parsed request body; dataString gives the raw text
    • request.pathParams: values from the relative path, like {id} in /incident/{id}
    • request.queryParams: query-string values
    • request.getHeader(name), plus uri and url

    With response you call setStatus() and setBody(), which serializes an object to the requested format (JSON or XML), or simply return an object from the script. You can also set headers.

    Good practice: validate input and return proper status codes (400 for bad input, 201 for created, 404 when a record isn't found), keep business logic in a script include so the REST script stays thin, version the API so you can change it without breaking consumers, and rely on authentication plus ACLs rather than hand-rolled checks.

    (function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
      var body = request.body.data;
      if (!body.short_description) {
        response.setStatus(400);
        response.setBody({ error: 'short_description is required' });
        return;
      }
      var inc = new GlideRecord('incident');
      inc.initialize();
      inc.setValue('short_description', body.short_description);
      inc.setValue('caller_id', gs.getUserID());
      var id = inc.insert();
      response.setStatus(201);
      response.setBody({ sys_id: id, number: inc.getValue('number') });
    })(request, response);
    What interviewers listen for
    • request.body.data, pathParams, queryParams, getHeader
    • response.setStatus and response.setBody
    • Return meaningful HTTP status codes
    • Keep logic in script includes
    • Version the API to protect consumers
  30. 30.How do events and notifications work together? Show how you would fire a custom event from a business rule.mid

    An event is a record in the event queue (sysevent) saying "something happened". You register the name in the Event Registry, then queue it from a script with gs.eventQueue(name, record, parm1, parm2). Scheduled jobs process the queue and hand each event to whatever listens:

    • Email notifications set to Event is fired; they can take recipients from parm1 or parm2
    • Script actions, which run server-side code for the event
    • legacy workflow activities and inactivity monitors

    A notification can instead be sent when a record is inserted or updated (with conditions), or be triggered from a flow's notification step. Each defines who receives it, what it contains (subject, body, email scripts for dynamic content), and a weight: when duplicate notifications target the same record and recipients, only the highest weight is sent; weight 0 is always sent.

    Why use events? They decouple when something happens from what reacts, and processing is asynchronous, so the user's transaction isn't slowed.

    // After update business rule on incident
    (function executeRule(current, previous) {
      if (current.priority.changesTo(1)) {
        // name, record, parm1, parm2
        gs.eventQueue('x_acme_ops.incident.escalated', current,
          current.getValue('assignment_group'), gs.getUserName());
      }
    })(current, previous);
    What interviewers listen for
    • gs.eventQueue(name, record, parm1, parm2)
    • Register events in the Event Registry
    • Notifications, script actions listen to events
    • Send when: event fired, insert/update, or flow
    • Highest weight wins among duplicates; 0 always sends

    Likely follow-up: A user says they never got an email. How do you troubleshoot it?

  31. 31.How do SLAs work in ServiceNow? Explain SLA definitions, task SLAs and their conditions.mid

    An SLA definition (contract_sla) describes a target: the table (for example Incident), the duration (say 4 hours), the schedule (such as 8-5 weekdays, which decides business time) and a set of conditions. The type can be SLA (with a customer), OLA (between internal teams) or underpinning contract (with a vendor).

    When a task matches, the SLA engine attaches a task SLA (task_sla) record that tracks timing: start time, breach time, actual and business elapsed time and percentage, time left, and whether it has breached.

    Conditions:

    • Start: when the SLA attaches
    • Pause / Resume: stop and restart the clock, typically while On Hold awaiting the caller
    • Stop: when the SLA completes, for example when the incident is resolved
    • Cancel and Reset: cancel it, or complete it and attach a fresh one

    Task SLA stages are In progress, Paused, Completed and Cancelled. Notifications and escalations at thresholds such as 50% or 75% are usually driven by the SLA's flow. A common gotcha: if the pause condition overlaps the start condition badly, the SLA stays paused forever or gets cancelled.

    What interviewers listen for
    • Definition: table, duration, schedule, conditions
    • Task SLA record tracks timing per task
    • Start, pause/resume, stop, cancel, reset conditions
    • Schedule decides business elapsed time
    • SLA vs OLA vs underpinning contract
  32. 32.What is gs, and which GlideSystem methods do you use most?easy

    gs is the GlideSystem object, available in server-side scripts. The methods you reach for most:

    • User and session: getUserID(), getUserName(), getUserDisplayName(), getUser() (a GlideUser object), hasRole(), getSession(), isInteractive()
    • Logging: gs.info(), gs.warn(), gs.error(), gs.debug(), which accept {0}-style parameters. gs.log() exists only in global scope.
    • Messages to the user: addInfoMessage(), addErrorMessage(); getMessage() for translated text
    • Properties: getProperty(name, default), setProperty()
    • Events: eventQueue() and eventQueueScheduled()
    • Date helpers: beginningOfToday(), daysAgo() and friends, often used in queries
    • Utility: nil(), generateGUID(), tableExists()

    Like g_user.hasRole(), gs.hasRole() returns true for admin users. And session messages don't make sense in async code: addInfoMessage() isn't supported in async business rules.

    var me = gs.getUserID();
    if (gs.hasRole('itil')) {
      gs.info('Agent {0} opened the record', gs.getUserName());
    }
    var limit = parseInt(gs.getProperty('x_acme_app.max_rows', '100'), 10);
    gs.addInfoMessage(gs.getMessage('Record saved'));
    gs.eventQueue('x_acme_app.record.saved', current, me, '');
    What interviewers listen for
    • gs = GlideSystem, server-side only
    • getUserID, getUserName, hasRole, getUser
    • gs.info/warn/error/debug; gs.log is global only
    • getProperty with a default value
    • eventQueue fires events
  33. 33.How do users, groups and roles relate, and what is the best practice for granting access?easy
    • Users (sys_user) are people or integration accounts.
    • Groups (sys_user_group) are teams, such as a Service Desk or a Network group. They're used for assignment, approvals and notifications.
    • Roles (sys_user_role) grant permissions, like itil for fulfillers or catalog_admin. ACLs, modules, UI actions and scripts check roles.

    Roles can contain other roles, so granting one role can bring several others. A user gets roles directly or, preferably, by inheriting them from group membership.

    Best practice: assign roles to groups, not individual users. When someone joins the Network team they're added to the group and get the right access automatically; when they leave the group it's removed. That's easier to audit and matches how HR and identity systems provision people. Keep admin to a small set of people, and remember that some roles, like security_admin, are elevated: an admin must explicitly elevate to use them. Also, roles that grant fulfiller rights often have licensing implications, so check before handing them out.

    What interviewers listen for
    • Users, groups for teams, roles for permissions
    • Roles can contain other roles
    • Assign roles to groups, not directly to users
    • Limit admin; security_admin requires elevation
    • Fulfiller roles can affect licensing
  34. 34.Why shouldn't you call current.update() in a business rule, and what should you do instead?mid

    current.update() saves the record again, which triggers the insert/update business rules on that table again, which may call update() again. At best you get a double save with duplicate audit entries and notifications; at worst a recursion that the platform has to detect and stop. The docs say it's never necessary.

    What to do instead:

    • Before rules: just set fields on current. Changes are written automatically once all before rules finish.
    • After rules: use them to update related records, such as the parent problem or child tasks, not the current one.
    • Async rules: good for slow work; if you really must write back to the same record, keep it minimal and deliberate.

    In the rare case where you must update the current record from an after or async rule, setWorkflow(false) before update() suppresses business rules, but it also skips engines, notifications and audit-driven logic, so treat it as a last resort and document why.

    // Before update rule: just set the field, no update() needed
    (function executeRule(current, previous) {
      if (current.priority.changesTo(1)) {
        current.setValue('u_escalated', true);
      }
    })(current, previous);
    
    // After update rule: update a RELATED record, not current
    (function executeRule(current, previous) {
      var prb = current.problem_id.getRefRecord();
      if (prb.isValidRecord()) {
        prb.work_notes = 'Linked incident ' + current.getValue('number') + ' was escalated';
        prb.update();
      }
    })(current, previous);
    What interviewers listen for
    • update() re-triggers business rules: recursion risk
    • Before rules: set fields, they save automatically
    • After rules: update related records only
    • setWorkflow(false) skips BRs, engines and more
    • Docs: current.update() is never necessary
  35. 35.This script is meant to collect the sys_ids of active P1 incidents, but every entry in the array is the same. Why, and how do you fix it?hard

    inc.sys_id isn't a string. Dot-walking a field on a GlideRecord returns a GlideElement object, and the GlideRecord reuses its element objects as next() moves from row to row. So you push the same object reference on every iteration, and when you read the array afterwards every entry reflects the last row the record pointed at.

    The fix is to push a primitive string:

    • ids.push(inc.getValue('sys_id'))
    • ids.push(inc.getUniqueValue())
    • ids.push(inc.sys_id.toString()) or String(inc.sys_id)

    The same bug shows up with any field, for example building an object like { number: inc.number } inside a loop. That's one reason experienced developers use getValue() by default. Remember that getValue() returns null for empty fields and "0" or "1" for booleans, so compare accordingly.

    var ids = [];
    var inc = new GlideRecord('incident');
    inc.addQuery('active', true);
    inc.addQuery('priority', 1);
    inc.query();
    while (inc.next()) {
      ids.push(inc.sys_id); // bug
    }
    gs.info(ids.join(','));
    What interviewers listen for
    • gr.field returns a GlideElement, not a string
    • Elements are reused as next() advances
    • Array ends up with references to the same element
    • Use getValue(), getUniqueValue() or toString()
    • getValue returns null for empty, "0"/"1" for booleans
  36. 36.When a record is saved, in what order do business rules, engines and notifications run? Why does the business rule Order value matter?hard

    Per the docs, when a record is inserted or updated:

    • Before business rules with order below 1000
    • Before engines: approval, assignment rules, data policy, data lookup, escalation, field normalization and others, in no guaranteed order
    • Before business rules with order 1000 or higher
    • The database operation
    • After business rules with order below 1000
    • After engines: including the table notifications engine and the trigger engine that starts record-triggered flows
    • Email notifications, by weight
    • After business rules with order 1000 or higher

    Async rules run later, from a scheduled job created during the transaction. Display rules run only when a form loads, and query rules run before queries.

    So Order is more than tie-breaking. If you need a value that assignment rules or a data lookup will set, your before rule must be order 1000 or above. If you want to adjust something before the data policy engine checks mandatory fields, keep it below 1000. Client-side scripts always run before the form is submitted, so they come before all of this.

    What interviewers listen for
    • Before BRs under 1000, before engines, before BRs 1000+
    • Then the database operation
    • After BRs under 1000, after engines, notifications, after BRs 1000+
    • Async rules run later via a scheduled job
    • Order 1000 is the boundary around the engines
  37. 37.What is a before query business rule, and when would you use one instead of an ACL?hard

    A before query rule runs before the platform queries a table, and it can add conditions to current so that some rows are never returned. The base system's rule that limits which incidents users without the itil role can see is a well-known example.

    Compared with read ACLs:

    • The filtering is silent: users don't get the "rows removed by security constraints" message they get when ACLs strip rows from a list, and counts and pagination stay correct.
    • It happens in the database query, which usually performs better than evaluating ACLs row by row.
    • But it's a blunt instrument: it only restricts reads, it applies to every query on that table, including your own scripts, and it's easy to lock out integrations or reports. Always add a condition or early return for admins and system contexts.

    The docs also warn to use them sparingly, keep conditions on indexed fields and avoid lots of OR clauses. Security still belongs in ACLs; use query rules for data segregation that ACLs handle badly, not as a replacement for domain separation.

    // Before, Query checked, table: x_acme_vendor_case
    (function executeRule(current, previous) {
      if (gs.hasRole('x_acme.case_admin') || !gs.isInteractive()) {
        return;
      }
      // vendors only ever see their own company's cases
      current.addQuery('company', gs.getUser().getCompanyID());
    })(current, previous);
    What interviewers listen for
    • Adds conditions before the query runs
    • Silently hides rows; no "removed by security" message
    • Usually faster than row-by-row ACL evaluation
    • Applies to every query, including scripts: add exits
    • Keep conditions simple and indexed; use sparingly
  38. 38.How do you call an external REST API from ServiceNow in script? Where should that call run?mid

    Use RESTMessageV2 from the sn_ws namespace. Two styles:

    • Named REST Message records (System Web Services > Outbound > REST Message): store the endpoint, HTTP methods, headers, authentication and variable substitutions like ${title}. Scripts call new sn_ws.RESTMessageV2('Ticketing API', 'Create ticket') and fill variables with setStringParameter() or setStringParameterNoEscape().
    • Ad hoc: new sn_ws.RESTMessageV2() with setEndpoint(), setHttpMethod(), setRequestHeader(), setRequestBody().

    execute() returns a RESTResponseV2 with getStatusCode(), getBody() and haveError(). Authentication goes through setBasicAuth() or, better, an authentication profile such as OAuth 2.0 via setAuthenticationProfile(). For systems inside the corporate network, setMIDServer() routes the call through a MID Server.

    Where to run it: never in a before rule that blocks the user's save. Use an async business rule, an event with a script action, or a flow with an IntegrationHub REST step, and handle timeouts, errors and retries explicitly.

    var rm = new sn_ws.RESTMessageV2('Ticketing API', 'Create ticket');
    rm.setStringParameterNoEscape('title', current.getValue('short_description'));
    rm.setRequestHeader('Content-Type', 'application/json');
    rm.setHttpTimeout(10000);
    try {
      var resp = rm.execute();
      if (resp.getStatusCode() == 201) {
        var body = JSON.parse(resp.getBody());
        gs.info('Created external ticket ' + body.id);
      } else {
        gs.error('Ticketing API failed: ' + resp.getStatusCode() + ' ' + resp.getBody());
      }
    } catch (e) {
      gs.error('Ticketing API error: ' + e.message);
    }
    What interviewers listen for
    • sn_ws.RESTMessageV2, named or ad hoc
    • execute() returns status code and body
    • Use auth profiles (OAuth) rather than hard-coded creds
    • setMIDServer for endpoints behind the firewall
    • Run asynchronously and handle errors and timeouts
  39. 39.What is IntegrationHub, and what is a spoke?mid

    IntegrationHub extends Flow Designer (Workflow Studio) with integration capabilities, so integrations are built as flow actions rather than scripts.

    • A spoke is a scoped application bundling Workflow Studio content (actions, sometimes subflows and triggers) for one system or domain: for example Slack, Microsoft Teams, Jira or Azure AD. You drop an action like "Create Jira issue" into a flow and fill in its inputs with data pills.
    • Some spokes come with the platform or the parent application, such as the ITSM spoke; many third-party spokes require an IntegrationHub subscription, and usage is licensed.
    • When there's no spoke, you build a custom action using steps such as the REST step, SOAP step or JSON parser; higher tiers add steps like PowerShell, SSH and JDBC, which typically run through a MID Server.
    • Connection and credential aliases keep endpoints and secrets out of the action, so the same flow works in dev, test and prod with different connections.

    Why interviewers care: it's the low-code, upgrade-friendly alternative to hand-written RESTMessageV2 scripts, and it gives you reusable, testable, observable integrations.

    What interviewers listen for
    • Adds integration actions to flows
    • Spoke: scoped app of actions for one system
    • Custom actions with REST, SOAP and other steps
    • Connection and credential aliases per environment
    • Many spokes need an IntegrationHub subscription
  40. 40.What is a MID Server, how does it communicate with the instance, and what is it used for?mid

    A Management, Instrumentation and Discovery (MID) Server is a Java application you install on a Windows or Linux host inside your network. It lets a cloud instance reach systems it can't reach directly.

    How it talks to the instance: the MID Server always initiates the connection outbound over HTTPS, so you don't open inbound firewall ports. Work is exchanged through the ECC Queue (ecc_queue): the instance writes output records for a MID Server, the MID Server picks them up (it's notified through the message bus and also polls periodically), does the work, and writes input records with the results.

    Common uses:

    • Discovery and Service Mapping, scanning the network to populate the CMDB
    • Integrations with internal systems: JDBC or LDAP imports, REST or SOAP calls via setMIDServer(), IntegrationHub PowerShell and SSH steps
    • Event Management and metric collection

    Operational points: validate a new MID Server before use, run several for capacity and failover (clusters), give each only the capabilities and IP ranges it needs, and note that MID Servers upgrade automatically to match the instance.

    What interviewers listen for
    • Java app on a host inside the customer network
    • Outbound HTTPS only; no inbound ports needed
    • Work exchanged via ECC Queue output and input records
    • Discovery, Service Mapping, internal integrations
    • Validate, cluster for failover, auto-upgrades
  41. 41.How do you run a script on a schedule in ServiceNow, and what should you watch out for?easy

    The classic tool is a Scheduled Script Execution (a scheduled job, sysauto_script), under System Definition > Scheduled Jobs. You pick when it runs (daily, weekly, monthly, periodically, once or on demand), a Run as user and optionally a condition script, then write the server-side script. Behind the scenes the scheduler creates sys_trigger entries.

    Alternatives: a flow with a scheduled trigger for low-code logic, scheduled data imports for integrations, and scheduled reports.

    Things to watch:

    • It runs non-interactively: no gs.addInfoMessage(), no form, no user session context, and the Script Debugger can't pause it. Log with gs.info().
    • Choose Run as carefully; the job gets that user's access.
    • Process large volumes in batches with setLimit() and indexed queries, rather than one giant transaction.
    • Schedule heavy jobs outside business hours, and make them safe to re-run if they fail halfway.
    • Test in sub-production; "Execute Now" on a big job in prod is a classic outage.
    // Scheduled Script Execution, runs daily at 02:00 as a system user
    (function () {
      var stale = new GlideRecord('incident');
      stale.addEncodedQuery('state=6^resolved_at<javascript:gs.daysAgoStart(7)');
      stale.setLimit(500); // process in batches
      stale.query();
      while (stale.next()) {
        stale.setValue('state', 7); // Closed
        stale.update();
      }
    })();
    What interviewers listen for
    • Scheduled Script Execution with a schedule and Run as
    • Flows with scheduled triggers as a low-code option
    • Non-interactive: no session messages, log instead
    • Batch with setLimit and indexed queries
    • Run heavy jobs off-hours and make them re-runnable
  42. 42.What is the Automated Test Framework (ATF), and how do you use it in an upgrade or release process?mid

    ATF lets you build automated tests on the instance itself, without external tools.

    • A test is a sequence of steps: impersonate a user, open a new form, set field values, click a UI action, submit, then assert field values, visibility or mandatory state. There are server steps too, like record queries and Run Server Side Script (which supports Jasmine), plus Service Catalog, Service Portal, REST and custom UI steps.
    • Test suites group tests, can be nested, and can be scheduled. Browser-based steps run in a Client Test Runner tab; server steps run on the instance.
    • ATF rolls back the data a test creates when it finishes, and tests can be parameterized to run with multiple data sets.

    In a process: build tests for critical flows (incident creation, catalog ordering, approvals, key business rules), run the suite after every upgrade in dev and test, before promoting update sets, and in CI pipelines.

    Design tips from the docs: create your own test users and records instead of relying on existing data, avoid changing system tables, and don't run ATF in production; execution is disabled by default there through a system property.

    What interviewers listen for
    • Tests are steps: impersonate, form actions, asserts
    • Server-side script steps support Jasmine
    • Suites can be scheduled; client runner for UI steps
    • Test data is rolled back after the run
    • Create own test data; do not run in production
  43. 43.How is a Service Portal widget structured, and how do the client and server parts talk to each other?mid

    A portal is made of pages, pages have containers, rows and columns, and columns hold widget instances. A widget has:

    • HTML template: AngularJS markup bound to the controller, e.g. {{c.data.items}}
    • Client script: an AngularJS controller; by convention var c = this
    • Server script: runs on load, fills the data object, reads instance options and, on later calls, the input object sent from the client
    • Optional link function (DOM work), option schema (configurable instance options), CSS/SCSS and Angular providers (shared directives or services)

    Communication: the server script runs when the widget loads and data arrives as c.data. The client calls c.server.update() to send c.data back as input and rerun the server script, or c.server.get({ action: ... }) to send a custom payload. $sp gives server helpers like $sp.getParameter(); spUtil gives client helpers like recordWatch() and addInfoMessage().

    Best practices: clone base-system widgets instead of editing them, or embed them; always setLimit() queries; avoid unfiltered record watchers and auto-refresh loops.

    // Server script
    (function () {
      data.limit = options.limit || 5;
      if (input && input.action == 'refresh') { data.refreshedAt = new GlideDateTime().getDisplayValue(); }
      data.items = [];
      var inc = new GlideRecord('incident');
      inc.addQuery('caller_id', gs.getUserID());
      inc.addActiveQuery();
      inc.setLimit(data.limit);
      inc.query();
      while (inc.next()) data.items.push({ number: inc.getValue('number'), sys_id: inc.getUniqueValue() });
    })();
    
    // Client controller
    api.controller = function () {
      var c = this;
      c.refresh = function () { c.server.get({ action: 'refresh' }).then(function (r) { c.data = r.data; }); };
    };
    What interviewers listen for
    • HTML template, client controller, server script
    • Server fills data; client reads c.data
    • c.server.update() / get() send input back
    • Option schema makes widgets configurable
    • Clone or embed base widgets; limit queries
esc