← Back to homepage
Guide — ServiceNow Engineering

Where ServiceNow technical debt actually accumulates

Every individual customization looked fine when it shipped. The debt is in what nobody looked at again.

Written by the SwissNow IT team

Five places debt hides

None of these look wrong in isolation. The cost only shows up once there are hundreds of them across an instance nobody's fully mapped.

01

Business Rules with no condition

Firing on every insert or update on a busy table, most of the time doing nothing - and costing a transaction's worth of time every single time.

02

Duplicated logic across Script Includes

The same validation written three different, subtly inconsistent ways - a fix to one doesn't fix the other two.

03

Deprecated API usage surviving upgrades

Patterns that technically still work today, but quietly block a future platform upgrade from going smoothly.

04

Hardcoded sys_ids

A specific record baked directly into script instead of a real lookup - breaks silently the moment that record changes or gets recreated.

05

Missing error handling around integration calls

A REST call with no try/catch - one slow or malformed response away from a stuck transaction.

How to check

Most of this is mechanically checkable - it's the volume across a real instance that makes it tedious, not the difficulty of any one check.

Read business rule conditions, not just their scripts

A quick count of how many active Business Rules on a busy table have an empty Condition field is one of the fastest signals available - each one runs on every single insert/update whether it's relevant or not.

Grep for hardcoded sys_ids

A real, mechanical check - a 32-character hex string inside a script is almost always a hardcoded reference, and almost always worth replacing with a real lookup.

Check for synchronous calls with no timeout or catch

An outbound REST or SOAP call with no error handling doesn't just risk one failed integration - it risks the whole transaction hanging until the platform itself times it out.

Debt worth prioritizing

  • Business Rules with an empty Condition field on high-traffic tablesRunning unconditionally, on every write, whether relevant or not.
  • Script Includes with near-duplicate function bodiesThe same logic maintained in more than one place, drifting slightly further apart each time one gets touched.
  • Any GlideRecord loop with no setLimit()Fine on a small table today, a real problem the day that table grows.
  • Outbound calls with no try/catch around themA single slow third party away from blocking every transaction that touches this code path.
  • Customizations last touched by someone no longer at the companyNot wrong by default - but nobody currently on the team can explain why it works the way it does.

The manual version doesn't scale

A real code review pass means reading every relevant Business Rule, Script Include, Client Script, and UI Action - not once at launch, but again after every meaningful change, forever. Most teams do this reactively, when something breaks, instead of continuously - which means the debt is discovered by an incident, not by a review.

neo.ai

Running this review continuously, automatically

Our own platform, neo.ai, reviews Business Rules, Script Includes, UI Actions, and Client Scripts on a schedule for correctness, security, and best practice - and only surfaces what's genuinely actionable. It's one of seven categories it watches across a ServiceNow instance.