relationship-mapping
CI Relationship Mapping
Overview
CI relationships form the backbone of CMDB value. Without relationships, CIs are isolated islands of data. This skill covers:
- Understanding relationship types and their semantics
- Creating and validating relationships between CIs
- Analyzing dependency chains for impact assessment
- Detecting orphan CIs that lack relationships
- Maintaining relationship health over time
When to use: When modeling service dependencies, preparing for change impact analysis, auditing CMDB completeness, or troubleshooting service outages.
Value proposition: Well-mapped relationships enable accurate impact analysis, reducing change failures by up to 50% and decreasing MTTR during incidents.
Prerequisites
- Roles:
cmdb_adminoritilwith CMDB write access - Access: cmdb_rel_ci, cmdb_rel_type, cmdb_ci tables
- Knowledge: CI class hierarchy, dependency modeling concepts
- Related skills: Complete
cmdb/ci-discoveryfirst
Procedure
Step 1: Understand Relationship Types
ServiceNow provides relationship types in cmdb_rel_type. Each relationship has:
- Parent descriptor: How the parent relates to the child
- Child descriptor: How the child relates to the parent
Common Relationship Types:
| Relationship | Parent Descriptor | Child Descriptor | Use Case |
|---|---|---|---|
| Runs on | Runs on | Hosts | Application on Server |
| Depends on | Depends on | Used by | Service dependencies |
| Contains | Contains | Contained by | Physical containment |
| Connects to | Connects to | Connected by | Network connectivity |
| Sends data to | Sends data to | Receives data from | Data flows |
| Cluster of | Cluster of | Cluster member | Clusters |
| Uses | Uses | Is used by | Generic dependency |
Query available relationship types:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: active=true
fields: sys_id,name,parent_descriptor,child_descriptor
limit: 100
REST API:
GET /api/now/table/cmdb_rel_type?sysparm_query=active=true&sysparm_fields=sys_id,name,parent_descriptor,child_descriptor&sysparm_limit=100
Step 2: Query Existing Relationships
Before creating relationships, understand what exists:
Find all relationships for a CI:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent=[ci_sys_id]^ORchild=[ci_sys_id]
fields: parent,child,type,sys_created_on
limit: 50
Find downstream dependencies (what depends on this CI):
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: child=[ci_sys_id]^type.parent_descriptorLIKEDepends
fields: parent,parent.name,type,type.parent_descriptor
Find upstream dependencies (what this CI depends on):
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent=[ci_sys_id]^type.parent_descriptorLIKEDepends
fields: child,child.name,type,type.child_descriptor
Step 3: Create Relationships
Determine the correct relationship type first:
Decision Matrix:
| Parent CI Type | Child CI Type | Recommended Relationship |
|---|---|---|
| Application | Server | Runs on |
| Business Service | Application | Depends on |
| Server | Rack | Contained by |
| Server | Server | Connects to (if network) |
| Database | Server | Runs on |
| Load Balancer | Server Pool | Contains |
Find relationship type sys_id:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: nameLIKERuns on::Runs on
fields: sys_id,name,parent_descriptor,child_descriptor
Create the relationship:
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: [parent_ci_sys_id]
child: [child_ci_sys_id]
type: [relationship_type_sys_id]
Example - Application runs on Server:
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: "abc123..." # Application CI sys_id
child: "def456..." # Server CI sys_id
type: "55c95bf6c0a8010e0118ec7056e1c57d" # Runs on::Hosts
Step 4: Validate Relationships
Check for invalid relationships:
Find relationships with missing CIs:
Tool: SN-Execute-Background-Script
Parameters:
description: Find invalid relationships with missing CIs
script: |
var gr = new GlideRecord('cmdb_rel_ci');
gr.addQuery('parent.sys_idISEMPTY^ORchild.sys_idISEMPTY');
gr.query();
gs.info('Invalid relationships found: ' + gr.getRowCount());
while (gr.next()) {
gs.info('Invalid rel: ' + gr.sys_id + ' parent=' + gr.parent + ' child=' + gr.child);
}
Find duplicate relationships:
Tool: SN-Execute-Background-Script
Parameters:
description: Detect duplicate relationships
script: |
var duplicates = new GlideAggregate('cmdb_rel_ci');
duplicates.addAggregate('COUNT');
duplicates.groupBy('parent');
duplicates.groupBy('child');
duplicates.groupBy('type');
duplicates.addHaving('COUNT', '>', 1);
duplicates.query();
gs.info('Duplicate relationship combinations found: ' + duplicates.getRowCount());
while (duplicates.next()) {
gs.info('Duplicate: parent=' + duplicates.parent + ' child=' + duplicates.child + ' type=' + duplicates.type + ' count=' + duplicates.getAggregate('COUNT'));
}
Validate relationship type appropriateness:
Some relationship types are only valid for certain CI classes. Check the relationship type's parent_ci_class and child_ci_class fields if populated.
Step 5: Analyze Dependency Chains
Understanding full dependency chains is critical for impact analysis.
Get complete dependency tree (recursive):
Tool: SN-Execute-Background-Script
Parameters:
description: Build dependency tree for CI
script: |
var ciSysId = 'YOUR_CI_SYS_ID';
var maxDepth = 5;
var visited = {};
var tree = [];
function getDependencies(parentId, depth, direction) {
if (depth > maxDepth || visited[parentId]) return;
visited[parentId] = true;
var gr = new GlideRecord('cmdb_rel_ci');
if (direction === 'down') {
gr.addQuery('child', parentId);
gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
} else {
gr.addQuery('parent', parentId);
gr.addQuery('type.parent_descriptor', 'CONTAINS', 'Depends');
}
gr.query();
while (gr.next()) {
var targetId = direction === 'down' ? gr.parent.toString() : gr.child.toString();
var targetName = direction === 'down' ? gr.parent.name.toString() : gr.child.name.toString();
tree.push({
depth: depth,
direction: direction,
ci_name: targetName,
ci_sys_id: targetId
});
getDependencies(targetId, depth + 1, direction);
}
}
getDependencies(ciSysId, 1, 'down');
gs.info('Upstream dependencies (what depends on this CI):');
tree.forEach(function(item) {
gs.info(' '.repeat(item.depth) + item.ci_name);
});
Identify critical path:
Services with single points of failure have critical paths:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent.sys_class_name=cmdb_ci_service^type.parent_descriptorLIKEDepends
fields: parent.name,child.name,child.sys_class_name
Step 6: Detect Orphan CIs
Orphan CIs (those without relationships) reduce CMDB value and complicate impact analysis.
Find CIs with no relationships:
Tool: SN-Execute-Background-Script
Parameters:
description: Find orphan CIs with no relationships
script: |
var orphans = [];
var ciClasses = ['cmdb_ci_server', 'cmdb_ci_appl', 'cmdb_ci_database_instance'];
ciClasses.forEach(function(ciClass) {
var gr = new GlideRecord(ciClass);
gr.addQuery('operational_status', '1');
gr.query();
while (gr.next()) {
var relGr = new GlideRecord('cmdb_rel_ci');
relGr.addQuery('parent', gr.sys_id);
relGr.addOrCondition('child', gr.sys_id);
relGr.setLimit(1);
relGr.query();
if (!relGr.hasNext()) {
orphans.push({
sys_id: gr.sys_id.toString(),
name: gr.name.toString(),
class: ciClass
});
}
}
});
gs.info('Orphan CIs found: ' + orphans.length);
orphans.forEach(function(o) {
gs.info(' ' + o.class + ': ' + o.name + ' (' + o.sys_id + ')');
});
MCP Alternative - Query-based approach:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_ci_server
query: operational_status=1^sys_idNOT IN(SELECT parent FROM cmdb_rel_ci)^sys_idNOT IN(SELECT child FROM cmdb_rel_ci)
fields: name,ip_address,sys_class_name
limit: 50
Note: Complex subqueries may not work via REST API. Use background script for reliability.
Step 7: Maintain Relationship Health
Periodic cleanup script:
Tool: SN-Execute-Background-Script
Parameters:
description: Clean up invalid relationships
script: |
var deleted = 0;
// Delete relationships where parent CI was deleted
var gr = new GlideRecord('cmdb_rel_ci');
gr.addNullQuery('parent');
gr.query();
while (gr.next()) {
gr.deleteRecord();
deleted++;
}
// Delete relationships where child CI was deleted
gr = new GlideRecord('cmdb_rel_ci');
gr.addNullQuery('child');
gr.query();
while (gr.next()) {
gr.deleteRecord();
deleted++;
}
gs.info('Deleted ' + deleted + ' invalid relationships');
Update stale relationships: When a CI's operational status changes, relationships may need updates:
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_ci
query: parent.operational_status!=1^ORchild.operational_status!=1
fields: sys_id,parent.name,child.name,parent.operational_status,child.operational_status
Tool Usage Summary
| Operation | MCP Tool | REST Endpoint |
|---|---|---|
| List relationship types | SN-Query-Table | GET /cmdb_rel_type |
| Query relationships | SN-Query-Table | GET /cmdb_rel_ci |
| Create relationship | SN-Create-Record | POST /cmdb_rel_ci |
| Delete relationship | SN-Update-Record (set inactive) | DELETE /cmdb_rel_ci/{id} |
| Complex queries | SN-Execute-Background-Script | POST /api/sn_chg_rest/change |
| CI relationships API | N/A | GET /cmdb/instance/{id}/relation |
Best Practices
- Bidirectional Awareness: Remember relationships have two perspectives (parent/child)
- Minimum Relationships: Every operational CI should have at least one relationship
- Type Consistency: Use consistent relationship types across similar CI patterns
- Avoid Circular Dependencies: A should not depend on B if B depends on A
- Document Business Context: Use relationship attributes to explain why the relationship exists
- Regular Audits: Run orphan detection monthly; invalid relationship cleanup weekly
- Discovery Integration: Align manual relationships with discovery-created relationships
Troubleshooting
Relationship Not Showing in Dependency View
Symptom: Created relationship doesn't appear in CI dependency views
Cause: Relationship type not configured for dependency visualization
Solution: Check cmdb_rel_type record - ensure is_used_by and is_dependency flags are set appropriately
Duplicate Relationships After Discovery
Symptom: Same relationship exists multiple times Cause: Manual creation overlapped with discovery Solution: Run duplicate detection script; delete duplicates keeping discovery-created records
Circular Dependency Detected
Symptom: Impact analysis shows infinite loop warning Cause: CI A depends on B, B depends on C, C depends on A Solution: Review and break the circular chain; often indicates incorrect relationship type usage
Relationship Type Not Found
Symptom: Cannot find appropriate relationship type for use case
Cause: OOB types may not cover all scenarios
Solution: Create custom relationship type via cmdb_rel_type table (requires cmdb_admin)
Examples
Example 1: Map a Three-Tier Application
# 1. Identify the CIs
Business Service: "Customer Portal"
Web Application: "Portal Frontend"
App Server: "prod-app-01"
Database: "Portal DB"
DB Server: "prod-db-01"
# 2. Find relationship type sys_ids
Tool: SN-Query-Table
Parameters:
table_name: cmdb_rel_type
query: nameLIKEDepends on^ORnameLIKERuns on
fields: sys_id,name,parent_descriptor
# 3. Create relationships (batch in one message)
# Service depends on Web App
SN-Create-Record: cmdb_rel_ci
parent: [service_sys_id], child: [webapp_sys_id], type: [depends_on_type]
# Web App runs on App Server
SN-Create-Record: cmdb_rel_ci
parent: [webapp_sys_id], child: [appserver_sys_id], type: [runs_on_type]
# Web App depends on Database
SN-Create-Record: cmdb_rel_ci
parent: [webapp_sys_id], child: [database_sys_id], type: [depends_on_type]
# Database runs on DB Server
SN-Create-Record: cmdb_rel_ci
parent: [database_sys_id], child: [dbserver_sys_id], type: [runs_on_type]
Example 2: Orphan Detection and Remediation
# 1. Find orphan servers
Tool: SN-Execute-Background-Script
Parameters:
script: [orphan detection script from Step 6]
# 2. For each orphan, determine what it hosts
Tool: SN-Query-Table
Parameters:
table_name: cmdb_ci_appl
query: install_dateLIKE[orphan_ip_address]
fields: name,sys_id
# 3. Create missing relationships
Tool: SN-Create-Record
Parameters:
table_name: cmdb_rel_ci
data:
parent: [app_sys_id]
child: [orphan_server_sys_id]
type: [runs_on_type_sys_id]
Related Skills
cmdb/ci-discovery- CI creation and classificationcmdb/impact-analysis- Using relationships for impact analysiscmdb/data-quality- CMDB data quality managementitsm/change-management- Changes and CI relationships
References
More from happy-technologies-llc/happy-platform-skills
happy-platform-skills
Reusable development patterns and automation recipes for enterprise platforms - 180+ skills across 23 categories
17scheduled-jobs
Comprehensive guide to creating and managing ServiceNow scheduled jobs - run frequencies, conditional execution, performance optimization, error handling, and debugging
4flow-generation
Generate ServiceNow Flow Designer flows from natural language descriptions including triggers, actions, conditions, subflows, approval flows, notification flows, and data manipulation flows
4application-scope
Manage scoped application development including setting application context and update set alignment
4scripted-rest-apis
Comprehensive guide to creating, securing, and testing Scripted REST APIs in ServiceNow for custom integrations and external system connectivity
4automated-testing
Comprehensive Automated Test Framework (ATF) guide for creating, managing, and executing automated tests in ServiceNow
4