Chidi Okwudire IT Professional. ERP Enthusiast. NetSuite Certified (Administrator, SuiteCloud Developer II, and ERP Consultant). Celigo Certified (Level 4+). Passionate About Empowerment Through Knowledge Sharing. Always Eager to Learn.

Learn How To Create a NetSuite Server-Side Script Delay (“Sleep”)

4 min read

TL;DR

SuiteScript does not offer a native way to pause the execution of your server-side script if you need to. While there are several ways to mimic a “sleep” action, the most reliable option is to use a delay service (or build your own).

Challenge

When integrating NetSuite with other systems, you might encounter APIs that define a throttling limit. Throttling is a safeguard built into most APIs to limit the number of calls that you can make to a given endpoint in a specific amount of time. Throttling limits widely vary; some APIs will allow several calls per second while others might limit you to a few calls every minute.

Recently, I worked on an integration with an API that had a very high throttling limit of 1 call per minute for one of its endpoints! We knew up front that there would be business scenarios in which we would not meet this requirement. Therefore, we needed a reliable way to inject a delay between API calls. It turns out that NetSuite does not provide any clean means to implement server-side delays so we needed to look elsewhere.

Solutions

Most of the solutions you’ll find out there are pretty much unreliable hacks which I do not recommend. Here are the most popular ones:

  1. Write a function like this one that idles away in a while loop until the desired amount of time elapses. This concept is known as busy-waiting or spinning in the software development world and is generally considered an anti-pattern that wastes useful processor time. Moreover, users have reported NetSuite throwing an SSS_INSTRUCTION_COUNT_EXCEEDED error when the delay exceeds 1 – 2 minutes. Avoid this approach.
  2. Perform a “slow” task in NetSuite, e.g., load a large file, run a complex (transaction) search with many rows, or call a SuiteScript API that is known to be slow. These are all variants of the same hack: Do something you don’t care about in the hope that sufficient time will elapse. This approach is unreliable as the time taken to execute your operation will vary (i.e. imprecise), NetSuite may silently optimize your search, etc. So you can never be sure you’ve waited long enough. Again, not an attractive solution.

If you’re familiar with JavaScript, you might be wondering about setTimeout(). Well, setTimeout() will only work in client-side scripts as it has a dependency on the window object. Similarly, all libraries which I tried at the time of writing, e.g., EasyTimer.js, produced an error due to a dependency that NetSuite’s SuiteScript environment does not support.

Let’s now consider a few viable solutions.

Use Batching

Batching is a process of combining multiple calls into one. While batching is not strictly a solution for dealing with throttling limits, it might enable you to avoid the problem altogether. So, before considering other solutions, be sure you’ve investigated and, where possible, batched your API calls as this is a good practice in any case.

Use Client-Side Delays

As mentioned above, JavaScript’s setTimeout() function is supported by all major browsers and will work on client-side. Thus, if your solution allows for it, you could move the delay to client-side and leverage setTimeout(). If you go this way though, be careful not to compromise user-experience. In fact, user-experience experts might argue that adding explicit delays on client-side is an anti-pattern.

Use a Delay Service

If your delay must be executed on server-side, you’ll need to look elsewhere as NetSuite does not offer a solution. Gladly, there are various free, open-source implementations on Github that you can use, for example, Flash or Slowwly. Although these services are intended to mimic a slow server, you can also use them to produce a delay.

External delay services are the most attractive way to achieve a server-side "sleep" in NetSuite. Use one out there or host yours. Click To Tweet

If you so desire, you can also spurn your own implementation and host it on Heroku, AWS, or wherever you want. The choice is yours though I personally do not fancy or recommend reinventing the wheel. So, if there’s a dependable service out there, I’d rather use it than create my own.

Speaking about dependability, the services referenced above do not provide any uptime guarantees and may be pulled offline without notice. That’s a risk that might be prohibitive depending on your use case.

Good news: While discussing this challenge some time back in the NetSuite Professionals Slack community, a member spontaneously and graciously offered to make their internal delay service available exclusively to the NetSuite community. We would like to thank Darren Hill from ExtendApps for this gesture! Since they use the solution internally, it comes with a higher degree of confidence than random services out there. To prevent abuse, I will not share the URL here. Feel free to contact Darren directly or reach out at stories[at]netsuite-insights.com if you’ll like to make use of this service.

Considerations

Barring future support of server-side delays in NetSuite, using a delay service is our recommended solution for the delay challenge as it involves no hacks and offers the desired level of precision. Nevertheless, here are a few things to bear in mind:

  1. Some delay services include a redirection feature. The idea is that you can provide your actual API call payload to the service and, after the delay, it will make the call for you. From a security perspective, this is a no-go! Avoid passing your API calls through random 3rd party services as you might expose security keys to unwanted persons. Instead, make two separate calls from within your NetSuite script – One to your delay service, followed by your actual API call.
  2. Regardless of whether you build the delay service yourself or use one from someone else, it is a good idea to make the URL configurable via your app preferences or as a script parameter. In that way, if the delay service is down or needs replacement, you don’t have to go digging in your code.
  3. Even with your delay implementation in place, be sure your code includes error handling for throttling limit violations. Usually, the API documentation will include details of which HTTP code to expect if you violate throttling limits. Your error handling should be able to process that code if it is ever received.
  4. Consider just-in-time delays. Here’s what I mean by that: Remember my example where the API had a throttling limit of 1 call per minute? Based on the business process, we knew in advance that 70 – 80% of calls would be more than one minute apart so we won’t hit the throttling limit. So, instead of adding a delay to every call, and bearing an unnecessary overhead most of the time, we created an implementation that makes calls with no delays by default. Only if the API returns a throttling limit error code, would we “sleep” and then retry. In this way, we improve average process execution speed.

I hope this article has shed some light on your options when it comes to realizing delays in your NetSuite scripts.

Do you know any other approaches that we haven’t covered? Share it in the comments section or email us at stories[at]netsuite-insights.com

Subscribe for more NetSuite Insights and consider becoming a contributor if you have insights of your own to share.

Chidi Okwudire IT Professional. ERP Enthusiast. NetSuite Certified (Administrator, SuiteCloud Developer II, and ERP Consultant). Celigo Certified (Level 4+). Passionate About Empowerment Through Knowledge Sharing. Always Eager to Learn.

3 Replies to “Learn How To Create a NetSuite Server-Side Script Delay (“Sleep”)”

  1. Hi. Thanks for the article. Just out of curiosity, why does this:
    context.response.write(“window.close();”);
    work on a suitelet (server side) though trying to include this function in a setTimeOut function doesn’t work?
    thanks

  2. I’ve used a function to do this:

    It will count the milliseconds from the current time.

    const wait = (ms) => {
    const date = Date.now();
    let currentDate = null;
    do {
    currentDate = Date.now();
    } while (currentDate – date < ms);
    }

    1. Hi Wes,

      Thanks for sharing. The solution you suggest is called out in the article. It’s the (infamous) busy waiting approach. Beware as this might lead to a SSS_INSTRUCTION_COUNT_EXCEEDED error if the time duration is long enough.

      Cheers

Leave a Reply

Your email address will not be published. Required fields are marked *

×