gs.getProperty() in ServiceNow — Reading System Properties in Scripts

How to use gs.getProperty() to read system properties in ServiceNow scripts — with defaults, type handling, caching behaviour, and the patterns used in production Script Includes.

gs.getProperty() reads system properties stored in the sys_properties table. It is the standard way to make ServiceNow scripts configurable without hardcoding values — feature flags, API endpoints, thresholds, and toggles all belong in system properties.

Basic Usage

// Read a system property
var value = gs.getProperty('my.app.setting');
gs.log(value);
// Returns the property value as a string, or null if not found

With a Default Value

Always provide a default value. If the property does not exist, gs.getProperty() returns null without a default, which will cause null reference errors if you use the value directly.

// Returns 'default_value' if property not found
var value = gs.getProperty('my.app.setting', 'default_value');

// Practical examples
var maxRetries = gs.getProperty('my.integration.max_retries', '3');
var apiEndpoint = gs.getProperty('my.api.endpoint', 'https://api.example.com');
var featureEnabled = gs.getProperty('my.feature.enabled', 'false');

Type Handling — Everything is a String

System properties are always stored and returned as strings. You must convert them to the right type in your script:

// Boolean properties
var isEnabled = gs.getProperty('my.feature.enabled', 'false') === 'true';
if (isEnabled) {
    // feature is on
}

// Integer properties
var maxItems = parseInt(gs.getProperty('my.max.items', '100'));
var threshold = parseFloat(gs.getProperty('my.threshold', '0.75'));

// JSON properties (store complex config as JSON string)
var configStr = gs.getProperty('my.app.config', '{}');
var config = JSON.parse(configStr);
var timeout = config.timeout || 30;

Creating System Properties

Navigate to System Properties > All Properties > New to create a property. Key fields:

  • Name — use dot notation: myapp.module.setting
  • Value — the property value
  • Description — always fill this in — document what the property controls
  • Type — String, Integer, Boolean, Date, Password2
  • Private — true for sensitive values (passwords, API keys)

Caching Behaviour

System properties are cached. When you update a property, the new value is available to new sessions almost immediately (typically within a few seconds). Long-running background scripts that loop indefinitely may see stale values — if you need real-time property reads in a loop, use a GlideRecord query against sys_properties directly instead.

// For real-time reads in long-running scripts
var propGR = new GlideRecord('sys_properties');
propGR.get('name', 'my.app.setting');
var liveValue = propGR.getValue('value');

gs.getProperty() in Client Scripts

gs.getProperty() is a server-side method — it is not available in Client Scripts directly. To read a property on the client side, use a GlideAjax call to a Script Include, or pass the value through a hidden field or UI Action.

// Script Include (server side)
var MyUtils = Class.create();
MyUtils.prototype = Object.extendsObject(AbstractAjaxProcessor, {
    getAppSetting: function() {
        return gs.getProperty(
            this.getParameter('prop_name'),
            this.getParameter('default')
        );
    }
});

// Client Script (calling the Script Include)
var ga = new GlideAjax('MyUtils');
ga.addParam('sysparm_name', 'getAppSetting');
ga.addParam('prop_name', 'my.app.setting');
ga.addParam('default', 'fallback');
ga.getXMLAnswer(function(answer) {
    console.log('Property value: ' + answer);
});

Naming Conventions

Use consistent dot-notation naming for system properties:

  • myapp.feature.enabled — feature flags
  • myapp.integration.endpoint — external system URLs
  • myapp.limits.max_records — configurable thresholds
  • myapp.notifications.enabled — notification toggles

Always prefix with your application or scope name to avoid conflicts with ServiceNow's own properties.

Sensitive Values — Use Password2 Type

For API keys, passwords, or secrets stored as system properties, set the type to Password2. Password2 properties are encrypted at rest, masked in the UI, and not exported in Update Sets. Never store secrets as plain String properties.

// Reading a Password2 property (decrypts automatically)
var apiKey = gs.getProperty('my.api.secret_key');
// Value is decrypted and available as plain text in the script
// but is stored encrypted in the database

System properties in scoped applications

System properties created inside a scoped application are prefixed with the application scope — x_myapp.property_name. Reading a scoped property from within the same scope uses the same gs.getProperty() call; reading it from a different scope or from Global requires the full prefixed name. Use the scoped naming convention consistently: all properties for a scoped application should start with the application prefix to avoid name collisions with global properties and other scoped apps.

Encrypting sensitive property values

For property values that should not be visible in plain text — API keys, passwords, tokens — use the Encryption Context feature. Navigate to System Properties > Encryption Contexts, create a context, and configure properties in that context to be encrypted at rest. When retrieving an encrypted property with gs.getProperty(), the value is automatically decrypted for use in scripts but appears as encrypted text in the UI and database. This is more secure than storing credentials in plain text properties, though it is not a substitute for Connection and Credential Aliases for integration credentials — aliases are more structured and support rotation more cleanly.

// Read a property with a fallback default
var maxItems = parseInt(gs.getProperty('x_myapp.max_items', '100')) || 100;
var apiEndpoint = gs.getProperty('x_myapp.api.endpoint', '');
if (!apiEndpoint) {
    gs.error('Required property x_myapp.api.endpoint not configured', 'MyApp');
    return;
}

Related: gs object reference · gs.getUserID · Credential Aliases

System Properties vs Instance Properties

ServiceNow distinguishes between system properties (defined at the platform level) and custom properties you create for your applications. Both are stored in the sys_properties table and retrieved with gs.getProperty(), but custom application properties created within a scoped application are namespaced with the app's scope prefix. For example, a property in a scoped app named x_mycompany_myapp might be stored as x_mycompany_myapp.feature_flag.enabled. This namespacing prevents collisions between different applications and makes it immediately clear which app owns a given property.

Default Values and Null Safety

The two-argument form of gs.getProperty() is essential for production code. When a property does not exist, gs.getProperty('some.property') returns null. Null comparisons in JavaScript are a frequent source of silent bugs — code that does if (gs.getProperty('feature.enabled') == 'true') will silently evaluate to false if the property is missing, which may be the desired behaviour but can also mask misconfiguration. The safer pattern is gs.getProperty('feature.enabled', 'false'), which makes the default explicit and self-documenting. For numeric properties, always parse the result: parseInt(gs.getProperty('timeout.seconds', '30'), 10).

Cache Propagation Across Clustered Nodes

For most configuration use cases this delay is imperceptible, but for flags that control security-sensitive behaviour, plan for a brief propagation window and avoid toggling flags during high-traffic periods. The cache refresh is automatic; you do not need to call any explicit refresh method in normal usage.

Using getProperty in Business Rules and Script Includes

A common architecture pattern is to centralise property reads inside a Script Include rather than scattering gs.getProperty() calls across multiple Business Rules. This gives you one place to handle defaults, type coercion, and logging when a property is missing. The Script Include acts as a configuration API for the rest of your application:

var AppConfig = Class.create();
AppConfig.prototype = {
    initialize: function() {},
    getTimeout: function() {
        return parseInt(gs.getProperty('myapp.api.timeout', '30'), 10);
    },
    isFeatureEnabled: function(feature) {
        return gs.getProperty('myapp.feature.' + feature, 'false') === 'true';
    },
    type: 'AppConfig'
};

Centralising property access also makes it easy to swap in test values during development without touching production configuration. The debugging guide covers patterns for testing configuration-dependent logic in the Script Debugger.

Property Management at Scale

Instances with dozens or hundreds of custom properties benefit from a naming convention applied consistently from the start. A three-tier prefix works well: scope.domain.key — for example, itsm.sla.breach.threshold or hr.onboarding.email.enabled. Properties with the same first segment can be grouped and managed together in the System Properties UI. For Update Sets, properties are captured automatically when changed through the platform UI, but properties created or modified via script (using gs.setProperty()) must be manually added to the Update Set or managed through a separate data migration step.

Environment Detection Pattern

One of the most practically useful applications of gs.getProperty() is environment detection — building scripts that behave differently in development, test, and production without code changes. Define a property like instance.environment with value production, test, or development per environment, set through clone preservers so it survives clones. Scripts that send external notifications, trigger integrations, or write to external systems check this property and behave accordingly. An outbound webhook script that checks gs.getProperty('instance.environment', 'development') == 'production' before sending will never accidentally fire production webhooks from a developer's test environment, even if a full clone brought production data and configuration into that environment.

Property Security: What Should Not Be a Property

System properties are readable by anyone with access to the System Properties module, and in scoped app contexts, properties may be readable by scripts with the appropriate scope access. API keys, passwords, and other secrets should not be stored in system properties — use the Credentials module instead, which provides access-controlled, audited storage specifically designed for sensitive values. System properties are appropriate for configuration values like timeout durations, feature flags, endpoint URLs (not including authentication), and operational parameters. Drawing a clear line between "configuration" (properties) and "secrets" (credentials) at the start of a project prevents security findings during audits and avoids the awkward migration required when an auditor flags a password stored in a system property.

Bulk Property Management

Instances with many custom properties benefit from tooling to manage them systematically. A custom report on sys_properties filtered to your app's namespace prefix gives you a complete inventory. For properties that need to be synchronised across environments (like feature flags that should be identical in test and production), a comparison script that queries properties in both instances via the REST API and reports differences helps catch drift before it causes environment-specific behaviour. For properties that are environment-specific by design (endpoint URLs, environment labels), document which properties should differ and why — this documentation is invaluable during onboarding and when debugging environment-specific issues. The Credential Aliases framework handles the credentials side of cross-environment configuration; system properties handle everything else.

Want the complete reference?

This article is part of the NowSpectrum knowledge library. Browse all products for cheat sheets, interview prep, and deep-dive reference guides.

Browse All Products →
← Back to all posts