If you understand one concept about ServiceNow, make it this: everything is a record in a table. Users, groups, incidents, change requests, knowledge articles, forms, fields, business rules, even the dictionary itself — all stored as rows in the same relational database. This uniformity is what makes the platform so powerful and so consistent.
Tables
A table is a collection of records. Each table has a unique name (e.g., incident, sys_user, cmdb_ci) and a label shown in the UI ("Incident", "User", "Configuration Item").
Tables you will encounter on day one:
| Table name | Stores |
|---|---|
| sys_user | Users (people who can log in) |
| sys_user_group | Groups |
| sys_user_role | Roles |
| incident | Incident tickets |
| problem | Problem records |
| change_request | Change requests |
| kb_knowledge | Knowledge articles |
| cmdb_ci | Configuration Items (the CMDB) |
| task | The parent of most workflow records |
Records and the sys_id
A record is a single row in a table. Every record has these system fields automatically:
- sys_id — a unique 32-character globally unique identifier; the primary key
- sys_created_on, sys_created_by — creation timestamp and user
- sys_updated_on, sys_updated_by — last modification
- sys_mod_count — incremented on each update
The sys_id is opaque, immutable, and used everywhere — in URLs, in references between tables, in scripts. When two records on different instances need to be matched (e.g., during update set application), they are matched by sys_id.
Fields
Fields are the columns on a table. ServiceNow supports many field types beyond the standard SQL set:
| Type | Description |
|---|---|
| String | Short text, configurable max length |
| Integer / Decimal | Numbers |
| Boolean | True/false |
| Date / Date-Time | Calendar values |
| Choice | Single value from a fixed list (e.g., Priority: 1-Critical, 2-High…) |
| Reference | Foreign key to another table — typed to a specific table |
| Glide List | Many-to-many reference |
| Journal Input / Work Notes | Append-only audit text fields |
| HTML | Rich text |
| Script | Server-side JavaScript stored in a field |
The Dictionary
The schema of the schema. sys_dictionary is itself a ServiceNow table whose rows describe every column of every other table. Each dictionary entry records:
- Which table the column belongs to
- The column name and label
- The data type and length
- Default value, mandatory flag, read-only flag
- Reference target table (for reference fields)
When you "add a field to a table" in the ServiceNow UI, what happens behind the scenes is: a new row is inserted into sys_dictionary, and the platform regenerates the necessary database structure. This is why no DBA work is ever needed.
Table Inheritance: Extending a Table
ServiceNow supports an inheritance model where one table extends another. The most important example is the Task hierarchy:
task
├── incident
├── problem
├── change_request
├── sc_request (Catalog request)
├── sc_req_item (Requested item)
├── sc_task (Catalog task)
└── (dozens more)
Every record in incident is also a record in task. The Task table provides shared fields: number, short_description, assigned_to, state, priority, opened_at, etc. The child tables add their own specialised fields (e.g., incident.caller_id, change_request.cab_required).
This means you can query "all open work assigned to me regardless of type" simply with a single query against the task table.
Forms and Lists Are Auto-Rendered
Because every table's structure is fully described in the dictionary, ServiceNow's list view and form view are generated automatically — no front-end code per table. When you customise a form layout, you are editing metadata (sys_ui_section, sys_ui_element), not HTML.
This auto-rendering is why ServiceNow admins can roll out a custom application in days where a traditional development team would need weeks.
Naming Conventions
- System tables start with
sys_(e.g., sys_user, sys_dictionary, sys_script) - CMDB tables start with
cmdb_(e.g., cmdb_ci, cmdb_ci_server) - Service catalog tables start with
sc_ - Custom tables in a scoped application must start with the scope prefix (e.g.,
x_acme_proc_order)
Try It on Your PDI
- In the application navigator filter, type
sys_dictionary.listand press Enter - Filter by Table =
incident - You will see every field on the incident table, including system fields, parent task fields, and custom additions
- Open one entry — note the Reference target, default value, and dependent script fields
This single view is your map to the entire platform. Everything else builds on it.