Home / Question Hub / Scenario & General
Scenario & General Questions
Real interview scenarios and the classic platform questions — order of execution, reference qualifiers, sys_ids, scoped apps and more.
No questions match your search.
Scenario Based Questions
22 questionsACLs on the same target are ORed: if any matching ACL grants access, the user gets access. So a role granted write by one field ACL keeps write even if another ACL's condition fails. Deny is achieved by no ACL evaluating to true — not by an explicit "deny" rule.
A before query Business Rule on incident: if the user lacks the admin/itil_admin role, append current.addQuery('active', true). Inactive records simply never come back for other users — lists, reports and reference lookups all stay consistent.
Query BR using the logged-in user's group memberships:
(function executeRule(current, previous) {
if (gs.hasRole('itil')) {
return;
}
current.addQuery('assignment_group', 'IN',
gs.getUser().getMyGroups().toArray().join(','));
})(current, previous);
Pair with a read ACL for defense in depth — the query BR gives the clean UX, the ACL guarantees security on every access path.
A 10-minute synchronous script holds a worker thread and can block the workflow engine and related transactions. Fix: break the work into chunks — hand it to a scheduled job or events processed asynchronously, use a timer between iterations, and checkpoint progress so it can resume. Long-running logic never belongs inline in a workflow activity.
Display Business Rule counts children into g_scratchpad; an onLoad client script shows the message:
// Display BR
g_scratchpad.childCount = new IncidentUtils()
.countChildren(current.getUniqueValue());
// onLoad Client Script
if (g_scratchpad.childCount > 0) {
g_form.addInfoMessage('This incident has ' +
g_scratchpad.childCount + ' child incident(s).');
}
By default each RITM's flow starts independently. To sequence, drive the requested items from a parent flow/workflow: keep later items' tasks in a Pending state and advance them when the previous item completes (an after BR or flow on RITM state change triggers the next). Alternatively, use execution order logic inside a single flow that creates catalog tasks sequentially.
Create a Relationship record (System Definition → Relationships) on incident:
// Applies to table: incident, Queries from table: incident
(function refineQuery(current, parent) {
current.addQuery('caller_id', parent.getValue('caller_id'));
current.addQuery('sys_id', '!=', parent.getUniqueValue());
})(current, parent);
Then add the new related list to the incident form layout.
Use a View Rule (sys_ui_view_rule): its script/conditions can switch on current.isNewRecord() and set the target view. View rules run server-side at form render — cleaner than client-side URL rewriting.
Options, in preference order: report on a common parent table (e.g. task covers incident/problem/change); build a Database View joining the tables; or use Report Sources on the view. Mention the trade-off: database views can't be written to, bypass some ACL behavior (they need their own ACLs), and joins must be indexed.
Two standard answers: turn on field-level auditing and derive durations from sys_audit, or build a small custom "state duration" table populated by a Business Rule on state change — write a row with state, entered time, and close the previous row's exited time. The custom table reports much faster than crunching sys_audit. Metrics (metric definitions on state) is the OOB feature built for exactly this — name it and you win the question.
A scheduled job with Run type "On Demand" doesn't run on a timer — it executes only when triggered manually or from script (SncTriggerSynchronizer.executeNow()). Useful for heavy maintenance you want packaged, permissioned and logged like a job, but launched by a human or by another process.
Two runs can overlap and double-process. Defenses: make the job idempotent; add a mutex flag (system property or a "running" record checked and set at start, cleared in a finally-style pattern); or checkpoint via last-processed sys_id so a second run continues instead of restarting. Also mention: a job regularly exceeding its interval should be chunked (style guide §11.7).
Advanced reference qualifier on the field:
javascript: 'sys_idIN' + gs.getUser().getMyGroups().toArray().join(',')
Runs server-side each time the lookup opens, so it always reflects current membership.
Fire a future-dated event with gs.eventQueueScheduled('task.reminder', current, '', '', gdt) where gdt is now + 3 days, and a notification on that event; check the record is still open in the notification condition. Alternative: a daily scheduled job querying tasks assigned > 3 days and still open. Flow Designer's "Wait for duration" + condition is the modern low-code answer.
An onLoad client script using GlideAjax (or g_scratchpad from a display BR) to check the group's type, then hide the list:
g_form.hideRelatedList('incident.parent_incident');
Related-list visibility can't be conditioned declaratively per record, so scratchpad + hideRelatedList() is the accepted pattern.
Server-side UI Action: run a GlideAggregate COUNT on the related incidents, current.setValue('u_incident_count', count), current.update(), then action.setRedirectURL(current) to reload the form showing the value.
The complete answer has three layers: a query BR filtering to assignment_group IN user's groups (clean lists), a read ACL with the same logic (authoritative security on every path, including API), and an exemption for elevated roles. Saying only "ACL" or only "query BR" is a half answer — the pairing is the point.
Structure the answer: direction (inbound/outbound/bidirectional), mechanism (REST with Table/Import Set API inbound, RESTMessageV2 or IntegrationHub spokes outbound, MID Server for on-prem), frequency (real-time events vs scheduled batch), and reconciliation (coalesce keys, correlation IDs on both sides to prevent loops). E-bonding two ticketing systems is the classic example — correlation_id and correlation_display exist for exactly this.
This is OOB behavior worth understanding: the assigned_to dictionary has a reference qualifier restricting users to members of the selected group. Reproduce it with an advanced qualifier: javascript: 'sys_idIN' + new AssignmentUtils().getGroupMembers(current.assignment_group). Keywords the interviewer wants: reference qualifier, dependent field.
Jelly is the legacy XML-based templating language behind classic UI Pages and UI Macros — tags like <j:if> and <g:evaluate> mix markup with server logic. You mostly encounter it maintaining old UI pages; new development uses Service Portal widgets or Next Experience (UI Builder) components instead. Knowing when not to use it is the modern answer.
In Flow Designer, create the tasks in a loop or parallel branches with "Create Catalog Task" actions (or a single script step inserting the sc_task records). In classic Workflow, drop multiple Catalog Task activities after a parallel split so they open together rather than sequentially.
var grJob = new GlideRecord('sysauto_script');
if (grJob.get('name', 'Nightly Group Audit')) {
SncTriggerSynchronizer.executeNow(grJob);
}
Common Questions
22 questionsA reference qualifier filters which records a reference field offers. Three types: Simple (condition builder), Dynamic (a reusable, named filter definition — e.g. "Active ITIL users"), and Advanced (a javascript: expression returning an encoded query, which can use current for dependent lookups).
- Query Business Rules (rows filtered)
- Read ACLs (record, then fields)
- Display Business Rules (g_scratchpad filled)
- Form renders
- onLoad Client Scripts
- UI Policies (in Order)
Server first, then client; policies last — which is why they override client scripts.
- onSubmit Client Scripts (can cancel)
- Write ACLs / Data Policies
- Before Business Rules (order < 1000)
- Database write
- Workflows / Flows
- After Business Rules
- Notifications and email events
- Async Business Rules (later, via scheduler)
next() advances to the next row and returns whether one existed. hasNext() peeks — tells you if more rows exist without moving. _next() is identical to next(), needed when the table has an actual column named "next" (e.g. some rotation tables) that shadows the method.
On the table: Application Access settings — "Accessible from: All application scopes" and the allowed operations (read/create/update/delete). Script Includes have their own "Accessible from" setting. Cross-scope access is also governed by runtime cross-scope privileges (sys_scope_privilege), which record and enforce what one scope may call in another.
A scoped app has a private namespace (x_yourco_appname): its tables, scripts and APIs are isolated, other scopes need explicit permission, and some APIs are restricted. Global apps share the one global namespace — anything can touch anything. Scoped is the modern default (required for the Store); global remains common for legacy platform customization.
LDAP connects the instance to a directory (typically Active Directory) to import and keep users and groups in sync, and optionally to authenticate logins against the directory. Ingredients: LDAP server record, OU definitions, scheduled data loads, and a transform map to sys_user / sys_user_group. For SSO, LDAP auth has largely given way to SAML/OIDC.
Navigate to System Diagnostics → Stats (/stats.do) and read the Build name/tag, or check System Properties → glide.war. The release family (Xanadu, Yokohama, …) appears in the build name.
The 32-character hexadecimal GUID that uniquely identifies every record on the platform — the primary key of every table. It's globally unique in practice, immutable, and the value references actually store. In script: gr.getUniqueValue().
A one-way container filled by display Business Rules on the server and read by client scripts after the form loads. Use it whenever the client needs server data known at load time — it saves a GlideAjax round trip. It does not update live; it's a snapshot from render time.
Inside a mail script (sys_script_email): current (the triggering record), template, email (the outbound email object — email.setSubject(), addAddress()), email_action (the notification record), and event (with event.parm1/parm2 when event-triggered).
- Import Sets + Transform Maps (file upload or scheduled from a data source)
- Import Set API (REST) for programmatic loads
- LDAP sync for users/groups
- IntegrationHub spokes / RESTMessageV2 pulls
- Update Sets and app repo for configuration (not data)
- XML import directly onto a list for small one-offs
A platform feature that strips unsafe markup (scripts, event handlers, dangerous tags) from HTML fields when records are saved, protecting against stored XSS. Controlled by glide.html.sanitize.all_fields; specific fields can be excluded, which then becomes a security review item.
From Studio/App Engine: publish the scoped app to the application repository (versioned, installable on linked instances), to the ServiceNow Store (for vendors, after certification), or export as an XML/update set for manual moves. Publishing snapshots a version number; target instances install/upgrade from the repo.
deleteRecord() deletes the single record the GlideRecord is positioned on. deleteMultiple() deletes everything matching the query in one operation — much faster, but be careful: with certain engines/cascade rules it can behave differently around business rule execution. Never call deleteMultiple() without conditions on the query. Ever.
Add the dictionary attribute no_attachment=true to the table's collection record (or use ACLs on sys_attachment conditioned on table_name for role-based control). The attribute removes the paperclip entirely; the ACL approach lets some roles keep it.
Both compute the filter at runtime. Advanced is an inline javascript: expression on the dictionary entry — flexible but buried and unreusable. Dynamic points to a named Dynamic Filter Option, centrally defined and reusable across many fields, usually backed by a Script Include. Prefer dynamic when the same filter logic appears more than once.
Releases are named alphabetically by city and ship roughly twice a year (recent families: Washington DC, Xanadu, Yokohama). Check docs.servicenow.com release notes before the interview and be ready with two or three features relevant to your track — for recent releases that means Now Assist / generative AI capabilities, AI Agents, and Workspace/UI Builder improvements.
The honest structure for any "version A vs B" question: name one or two headline features the newer release introduced (Rome, for example, pushed Employee Center and mobile improvements; later releases pushed Next Experience UI and then generative AI), and mention that upgrades also bring deprecations worth checking in release notes. Interviewers are testing whether you track the platform, not memorized changelogs.
UI Policy: client-side form behavior — show/hide, read-only, mandatory, per view, needs the form. Data Policy: server-side enforcement of mandatory/read-only that also applies to imports, APIs and background updates — and can optionally be pushed to the UI. If the data must be valid no matter how it arrives, it's a Data Policy.
The mapping layer between an import set staging table and a target table: field maps, coalesce keys to decide insert vs update, and transform scripts for logic. Full detail lives on the Automation & Flows page.
Covered in depth on their own pages: Automation & Flows for Flow Designer/Workflow/Integration, Portal & Catalog for widgets and catalog items, and Scripting for the GlideRecord and GlideAjax drills.