Skip to main content


note- check latest version docs links as applicable or as per your instance version

 see also the video version


Health scan example items

Do not use current. update() in business rules

Do not update related tables in a before business rule!/guides/tokyo/now-platform/tpb-guide/business_rules_technical_best_practices

use of getRowCount() in GlideRecord

Do not use hard coded sys ids in scripts

never use current.update() in a workflow

client side code should not use GlideRecord

Client scripts should not use the eval() method!/guides/tokyo/now-platform/tpb-guide/scripting_technical_best_practices

client scripts should not use DOM manipulation!/guides/tokyo/now-platform/tpb-guide/scripting_technical_best_practices

google some yourself!

  • avoid global UI scripts
  • Scripts should not directly call Java packages
  • enable privacy on client callable script includes
  • Read ACLs should not contain GlideRecord
  • protect a system property if you do not wish for a system property on production to be overwritten via an update set - for example, if it contains environment-level settings - consider setting private=true
  • table transform maps generally do not need "Run business rules" enabled
  • JDBC Data Sources should have the "Use last run datetime" option checked
  • Standardisation of form labels the general principle is upper case letter followed by lower case letters for the first word, and next word(s) start with lower case examples
  • read only fields fields such as number, parent fields should be made read only via UI policy so these can't be overwritten
  • CA Validation: Mutual authentication establishes trust by exchanging secure sockets layer (SSL) certificates

  • check run as user on scheduled jobs



  • Use of javascript alert /prompt/confirm in client scripting
  • these should be avoided where possible in favor of ServiceNow native dialog boxes which are more pleasing to the eye for service portal, use spModal for classic UI, use glideModal for combined portal/classic scripts (as in service catalog client scripts, for example), see Appendix C below
  • Ref:!/reference/api/tokyo/client/c_GlideModalClientSideV3API
  • use of gs.log and other logging principles
    NEVER use it in ACLs as these may execute multiple times per form/list load consider debug level logging (gs.debug) particularly in scoped applications debug level logging can also be leveraged via a boolean system property when within particular script includes client side code should not contain console.log (as per ServiceNow health scan recommendation
  • Reference:!/guides/tokyo/now-platform/tpb-guide/debugging_best_practices 
  • use of try-catch-ex statements this is to be encouraged, particularly within script include functions, to allow controlled capture of errors particularly where subsequent code should still be run, as opposed to the code 'bombing out’ 
  • sensible commenting in scripts where possible, use the description box in a script to explain it's usage following type of comment per function is recommended 
  • use the condition field in business rules where possible
  • Prefix custom scripts (business rules, script includes) for example acme_business_rule_name
    When modifying OOTB objects, consider upgradeability – perhaps working on a copy is better?
  • see also ServiceNow KBA eBook (exportable as pdf):


Principles to consider when considering customising your instance

 General principles to follow

  • consider if a new table is required, or a new field, as there may be better ways of implementing the solution for Data Lookup tables
  • Check the ServiceNow roadmap to see whether the feature will be delivered out of the box in the near future – perhaps contact your Account Manager
  • consider if the solution has already been built by someone else on the servicenow store or share:!/share

Identify duplicate records in tables

See my custom widget & page suggestion

Loading tables with large numbers of rows

  • Loading a large table with results set to zero, to then apply the filter this is useful when querying large tables, particularly on production
  • in the below example we wish to load the incident table which on production which contains large number of records on production, using the ?sysparm_filter_only=true parameter in the url https://<your_instance>
  • then apply the filter you desire and run the query
  • Try it out!
  • SNUtils might perhaps have an equivalent option also

Linking notification (email) logs to the actual notification that was fired

check this table: sys_email_log

Code Search Suggestions

  • Use SNUtils
  • Use the script referenced here (don’t really need to do this if you have the SNUtils browser extension installed)
  • In a scoped app it can be easier:

Running your own Health Scan

  • Ideally it’s best if ServiceNow run the health scan for you, and with each tool release the customer may become more and more empowered to run their own scan
  • For a suggestion on how you might run your own using code, see
  • Also check out:

Tool Upgrades

  • always clone over the sub-prod instance prior to upgrading so that testing is valid
  • where you choose to skip updates and retain local object updates, consider documenting these somewhere. This will enable you to check why you retained a local object rather than having to do the analysis each time
  • any plugins / new features not enabled as part of the upgrade should be documented for future analysis so that the tool does not get too far behind in time

 Suggestions for naming update sets

  • The update set could contain the story number (perhaps ServiceNow or Jira reference), plus defect number in the case of a UAT defect, and update sequence (01, 02, etc) which indicates the order of deployment
  • The update set name could contain a very concise description and suffix could be the developer/admins initials, e.g. _RDS
  • You could build a form to help enforce the naming standards!   


Popular posts from this blog

ServiceNow check for null or nil or empty (or not)

Haven't tested these all recently within global/local scopes, so feel free to have a play! option 1 use an encoded query embedded in the GlideRecord , e.g.  var grProf = new GlideRecord ( 'x_cls_clear_skye_i_profile' ); grProf . addQuery ( 'status=1^ owner=NULL ' ); grProf . query (); even better use the glideRecord  addNotNullQuery or addNullQuery option 2 JSUtil.nil / notNil (this might be the most powerful. See this link ) example: if ( current . operation () == 'insert' && JSUtil . notNil ( current . parent ) && ! current . work_effort . nil ())  option 3 there might be times when you need to get inside the GlideRecord and perform the check there, for example if the code goes down 2 optional routes depending on null / not null can use gs.nil : var grAppr = new GlideRecord ( 'sysapproval_approver' ); var grUser = new GlideRecord ( 'sys_user' ); if ( grUser . get ( 'sys_id' , current . approver )){

Get URL Parameter - server side script (portal or classic UI)

Classic UI : var sURL_editparam = gs . action . getGlideURI (). getMap (). get ( ' sysparm_aparameter ' ); if ( sURL_editparam == 'true' ) { gs . addInfoMessage ( 'parameter passed ); } Portal : var sURL_editparam = $sp . getParameter ( " sysparm_aparameter " ); if ( sURL_editparam == 'true' ) { gs . addInfoMessage ( 'parameter passed ); }