AdvancedOracle NetSuiteSuiteScript 2.x / Map/Reduce

Avoiding governance limit errors in NetSuite Map/Reduce scripts

Question
how to avoid governance limit errors in NetSuite Map/Reduce scripts

Also searched as

  • netsuite map reduce script stuck in queued status
  • netsuite SSS_USAGE_LIMIT_EXCEEDED map reduce
  • map/reduce vs scheduled script governance netsuite
  • netsuite getRemainingUsage yield script

Short answer

A NetSuite Map/Reduce script gives each map or reduce invocation of a key its own fresh governance allotment instead of sharing one pool across the whole run, so most SSS_USAGE_LIMIT_EXCEEDED failures come from a single key doing too much work, not from the total record count. Fix it by moving heavy logic out of getInputData, keeping map and reduce functions idempotent and cheap per key, and checking runtime.getCurrentScript().getRemainingUsage() before expensive calls.

Applies to: SuiteScript 2.0 and 2.1 Map/Reduce script type, all NetSuite editions with SuiteCloud enabled

Design a Map/Reduce script that stays inside governance

  1. 1In getInputData, return a search or query object directly (search.create(...).run(), or query.runSuiteQL) rather than iterating results into an array in the stage itself; NetSuite paginates the input for you across the map stage.
  2. 2Keep getInputData's own logic light: it has its own governance budget and a hard 60 minute wall-clock limit before it fails with SSS_TIME_LIMIT_EXCEEDED, separate from the per-key budget used later.
  3. 3In the map stage, do one record's worth of work per key. If a single key needs to touch many related records (e.g. an order with 500 lines), split the work further upstream in getInputData so each key is small.
  4. 4Call runtime.getCurrentScript().getRemainingUsage() before any record.load, record.save, search.create.run() or N/https call inside map or reduce, and log a warning when it drops below a safety threshold such as 50 units.
  5. 5Use context.write(key, value) in map to hand data to reduce instead of doing lookups twice; reduce receives an array of values for each key so batch related work there.
  6. 6In summarize, iterate context.mapSummary.errors and context.reduceSummary.errors (both are N/error.SuiteScriptError maps keyed by input key) and log or email a digest instead of letting failures disappear silently.
  7. 7Check Customization > Scripting > Map/Reduce Script Status for the deployment to see per-stage progress and key counts; a script stuck in Queued is usually waiting on account concurrency, not failing.
  8. 8If a stage genuinely needs more than one execution's worth of work per key, redesign around N/task's MapReduceScriptTask to chain a follow-up script rather than trying to force more governance out of one deployment.

Why governance is allocated per key, not per run

A Scheduled Script (SuiteScript 2.x scheduled type) gets one governance pool for the entire execution, so a script processing 10,000 records shares that pool across all of them and commonly needs to reschedule itself with N/runtime and N/task to pick up where it left off.

Map/Reduce works differently on purpose: NetSuite invokes the map function once per key returned by getInputData, and each of those invocations is its own execution with its own governance allotment (1,000 units on standard accounts, higher with a SuiteCloud Plus license). The same applies to each reduce invocation, which receives all values written for a given key.

This means a Map/Reduce script that fails with SSS_USAGE_LIMIT_EXCEEDED is almost never failing because there are too many total keys. It is failing because one key's map or reduce function is doing too much work on its own, for example loading a large record with many sublists, running a heavy saved search, or making several synchronous N/https calls inside a single invocation.

define(['N/search', 'N/runtime'], function(search, runtime) {
  function map(context) {
    var remaining = runtime.getCurrentScript().getRemainingUsage();
    if (remaining < 50) {
      log.audit('Low governance', 'key=' + context.key + ' remaining=' + remaining);
    }
    var data = JSON.parse(context.value);
    // do one record's worth of work here
  }
  return { map: map };
});

The queued and pending states that are not errors

A Map/Reduce deployment sitting in Queued or Pending status on the Map/Reduce Script Status page is not stuck. NetSuite runs a limited number of Map/Reduce and scheduled script queues concurrently per account, and the concurrency limit depends on the account's provisioning and SuiteCloud Plus license, so deployments genuinely wait their turn behind other scheduled work, workflow actions and other Map/Reduce jobs.

If a deployment is queued for an unusually long time, check Setup > SuiteCloud Development Framework or Customization > Scripting > Script Deployments for other deployments with higher priority ('High' vs 'Medium'), and consider spreading heavy jobs across off-peak hours using the deployment's schedule rather than firing everything at midnight.

getInputData pitfalls that look like governance errors

Returning a fully materialized array from getInputData (for example .map()'ing over search results into a plain JS array) forces the getInputData stage itself to load and hold every row in memory and against its own governance and time budget, which can fail before map ever starts, with an error that looks unrelated to the eventual data volume.

Prefer returning the search object itself, a query.Query result, or an object of the form { type: 'search', id: 'customsearch_x' }. NetSuite then streams the input to the map stage in its own paginated internal process, which is far more resilient than a hand-rolled array.

Chaining and self-rescheduling for genuinely large jobs

When the total dataset is large enough that even well-designed keys risk the account's daily Map/Reduce concurrency or the job needs to run in controlled batches, use N/task's MapReduceScriptTask from a Scheduled Script or another Map/Reduce's summarize stage to kick off the next chunk instead of trying to process everything in one deployment invocation.

This also gives you a clean audit trail per run (each task submission is its own execution with its own log) which is much easier to debug than one long-running job whose logs are impossible to isolate by batch.

Common pitfalls

  • !Iterating search results into an array inside getInputData instead of returning the search or query object directly.
  • !Assuming a Queued deployment has failed and re-triggering it manually, which creates duplicate concurrent runs once the original clears the queue.
  • !Doing multiple record.load/record.save round trips per key in map when a single record.submitFields or a Query-based bulk update would use far fewer units.
  • !Ignoring context.mapSummary.errors and context.reduceSummary.errors in summarize, so individual key failures never surface until someone notices missing data.
  • !Writing non-idempotent logic in map or reduce (e.g. incrementing a counter record) that produces wrong totals when NetSuite retries a key after a transient failure.
  • !Scheduling several heavy Map/Reduce deployments at the same trigger time, causing self-inflicted queuing that looks like a platform problem.

How an ERP-grounded AI assistant handles this

ERPray can be pointed at a Map/Reduce script's execution log and the account's script deployment records and explain, in plain terms, which stage and which specific key exceeded governance, whether the account was simply queued behind other jobs, and whether the fix is a code change or a scheduling change. For teams maintaining many Map/Reduce customizations, SyteRay-style grounded review of the getInputData return shape is often enough to catch the array-materialization mistake before it ships.

Frequently asked questions

Does SuiteCloud Plus change Map/Reduce governance limits?

Yes. Accounts with a SuiteCloud Plus license get a higher per-invocation unit allotment for the map, reduce and summarize stages than standard accounts, which is why the same script can behave differently across a production account and a sandbox without the add-on provisioned.

Why does my Map/Reduce script show far fewer keys processed than records in the search?

Check whether getInputData is returning a search with a row limit, whether a saved search has a maximum results setting, or whether the search itself uses a formula filter that is silently excluding rows. The Map/Reduce Script Status page's key count reflects what getInputData actually returned, not the full dataset you expect.

Can I increase the concurrency limit for Map/Reduce scripts?

Concurrency is tied to account provisioning and license level rather than a deployment setting. If jobs are consistently queued behind each other, the practical fix is to stagger schedules, raise deployment priority for time-sensitive jobs, or consolidate several small Map/Reduce scripts into fewer, better-batched ones.

Is it safe to call an external REST API from inside the map stage?

It works but each N/https call consumes governance units and adds latency per key, which multiplies across every invocation. Batch external calls where the API supports it, or move the integration to a Scheduled Script that processes accumulated results, rather than calling out once per record inside map.

Related

Advanced

Authenticating NetSuite RESTlets with OAuth 2.0 and Token-Based Authentication

NetSuite RESTlets can be called with either Token-Based Authentication (TBA, OAuth 1.0a signed requests) or OAuth 2.0, and both require a Setup > Integrations > Manage Integrations record before any token is issued. Machine-to-machine OAuth 2.0 uses a client credentials grant with a JWT bearer assertion signed by a certificate; TBA uses a consumer key/secret plus a per-user access token signed with HMAC-SHA256.

Advanced

Working with NetSuite's SuiteTalk REST Web Services API

SuiteTalk REST exposes NetSuite records at https://ACCOUNTID.suitetalk.api.netsuite.com/services/rest/record/v1/{recordType}/{id} and ad hoc SQL-like queries at /services/rest/query/v1/suiteql, both authenticated with TBA or OAuth 2.0. It returns JSON, paginates large result sets with limit/offset and a hasMore flag, and needs expandSubResources or a specific fields query to pull sublist and related data efficiently.

Advanced

Managing NetSuite sandbox refresh alongside SDF deployments

A NetSuite sandbox refresh clones production data and customization state into the sandbox account, which means any sandbox-only changes not captured in an SDF (SuiteCloud Development Framework) project are wiped, while changes that were already deployed to production survive because they come along with the refresh. Plan refreshes around your deployment calendar, and redeploy or validate your SDF project immediately after every refresh.

Error fix

Fix NetSuite SSS_USAGE_LIMIT_EXCEEDED Error

SSS_USAGE_LIMIT_EXCEEDED fires when a SuiteScript execution consumes all the governance units (usage points) allotted to its script type before it finishes. Fix it by checking runtime.getCurrentScript().getRemainingUsage() before expensive calls, yielding or rescheduling in Scheduled scripts, and moving heavy record-count work into Map/Reduce, which yields automatically across stages.

Error fix

Fix NetSuite INVALID_FLD_VALUE Error

INVALID_FLD_VALUE means NetSuite rejected a value you tried to set on a field because it does not match the field's expected type, list option, or reference record. Fix it by confirming the internal ID or text value actually exists on that field's source list and matches the field's value type (text versus list versus record reference) before setting it.

Error fix

Fix NetSuite SSS_MISSING_REQD_ARGUMENT Error

SSS_MISSING_REQD_ARGUMENT means a NetSuite API call, most often record.create(), record.load(), or search.create(), was called without a parameter that method requires, such as type or id. Fix it by checking the object literal you passed against the current SuiteScript 2.x API signature and confirming no required key is undefined at runtime.

AI for ERP

AI for NetSuite, Beyond the Built-In Text Tools

NetSuite's built-in AI covers text generation, not grounded answers on your own data. See how a private LLM over SuiteQL adds real Q&A and controls.

AI for ERP

AI agents for NetSuite manufacturing operations

AI agents for NetSuite manufacturing: WIP tracking, routing exceptions, and work order status grounded in SuiteQL, with human approval on anything that writes back.

Stuck on Oracle NetSuite?

Talk to engineers who work inside Oracle NetSuite every week, and who build private AI that answers these questions from your own ERP data.