A routing script may begin with two conditions and grow into a fragile wall of nested if-else statements. This practical build moves category, subcategory and technology routing into a Decision Table, keeps the Business Rule small and gives process owners one readable place to maintain mappings.
| Category | Subcategory | Technology | Assignment group |
|---|---|---|---|
| Software | Microsoft 365 | Messaging Support | |
| Infrastructure | Database | Oracle | Database Operations |
| Infrastructure | Web server | Apache | Middleware Support |
Use case and expected result
A support organisation receives incidents for several technologies. The combination of Category, Subcategory and Technology must select the correct Assignment group. The mapping changes regularly, but the logic should not require a code release every time a group changes.
| Category | Subcategory | Technology | Expected group |
|---|---|---|---|
| Software | Microsoft 365 | Messaging Support | |
| Infrastructure | Database | Oracle | Database Operations |
| Infrastructure | Web server | Apache | Middleware Support |
Decision Tables are a good fit when known combinations of inputs produce a deterministic result. They are not a replacement for procedural processing or complex record manipulation.
Why the long if-else approach becomes risky
- A business mapping is hidden inside code.
- Every mapping change needs script editing and regression testing.
- Overlapping branches and spelling differences are difficult to detect.
- Hard-coded sys_ids make promotion between instances unsafe.
if (category == 'software' && subcategory == 'email' && technology == 'm365') {
current.assignment_group = messagingGroup;
} else if (category == 'infrastructure' && subcategory == 'database' && technology == 'oracle') {
current.assignment_group = databaseGroup;
} else if (...) {
// More mappings keep growing here
}Step-by-step implementation
- 01Navigate to All > System Definition > Decision Tables and select New.
- 02Name the table Incident assignment routing and select Incident as the answer table when a record reference answer is required.
- 03Create inputs for Category, Subcategory and Technology. Match their types with the source data. Do not compare a display value with an internal choice value.
- 04Create one answer named Assignment group with a reference to User Group [sys_user_group].
- 05Add decision rows for the approved mappings. Put the most specific rows above broader fallback rows when first-match behaviour is used.
- 06Add an intentional fallback result, such as Service Desk, or let the calling logic handle no answer.
- 07Activate the table only after the test combinations have been reviewed.
Exact navigation labels can vary by ServiceNow release and installed applications. Search for Decision Tables in the Application Navigator if the module is placed differently.
Consume the decision without hard-coded groups
Use the platform-generated API details shown on your Decision Table definition. Input and result names depend on the definition, so copy the generated identifiers from your instance rather than guessing them. The example below shows the safe pattern.
(function executeRule(current, previous) {
var inputs = {
category: current.getValue('category'),
subcategory: current.getValue('subcategory'),
technology: current.getValue('u_technology')
};
// Replace the definition id and API call with the generated snippet
// displayed by your Decision Table in this instance.
var result = new sn_dt.DecisionTableAPI()
.getDecision('YOUR_DECISION_DEFINITION_SYS_ID', inputs);
if (result && result.result_elements &&
result.result_elements.assignment_group) {
current.setValue('assignment_group',
result.result_elements.assignment_group);
} else {
gs.warn('No assignment decision matched incident ' + current.getValue('number'));
}
})(current, previous);Do not paste a random API signature into production. Use the generated code snippet from the Decision Table record because return structure and scoped API usage can differ by configuration and release.
Testing checklist
- Run the Decision Table's own test capability first.
- Test the consuming Business Rule with a real non-production record.
- Verify internal values, not only labels visible on the form.
- Confirm the Assignment group is not overwritten by another Business Rule, Flow or assignment rule.
| Test | Input | Expected evidence |
|---|---|---|
| Exact match | Software / Email / Microsoft 365 | Messaging Support returned |
| Second row | Infrastructure / Database / Oracle | Database Operations returned |
| No match | Unknown combination | Fallback used or warning logged |
| Missing input | Technology empty | No incorrect broad match |
| Inactive row | Matching row deactivated | Row is not selected |
| Regression | Existing approved combinations | Results remain unchanged |
When to use which option
| Requirement | Recommended option |
|---|---|
| Many readable input-to-result mappings | Decision Table |
| Simple record conditions and field updates | Business Rule or Flow |
| Reusable procedural server logic | Script Include |
| Data-driven lookup maintained as records | Lookup table with controlled access |
| Dynamic orchestration across actions | Flow Designer |
The maintainable design is usually a small caller plus a visible decision model. Keep data mapping in the table and procedural work in reusable server-side logic.
Explore more implementation-focused ServiceNow and architecture guides.