NetSuite developer and admin guide, updated for 2026

NetSuite SuiteScript 2.x and 2.1: The 2026 Guide to Migration, Governance Limits, and Common Errors

SuiteScript is how you extend NetSuite beyond point-and-click setup, and 2026 changed the ground rules. SuiteScript 2.1 is now the standard, Oracle has published a firm retirement timeline for older versions, and new AI modules run only on 2.1. This guide covers what changed, how to migrate, the governance limits every script runs under, and how to fix the errors teams hit most often. If scripts are already failing in production, our NetSuite support services team can help today.

What is SuiteScript 2.x?

SuiteScript 2.x is NetSuite's JavaScript framework for customizing and automating the platform beyond standard configuration. It uses a modular architecture in which each script declares the NetSuite modules it needs. SuiteScript 2.1 is the current standard: it runs on a modern JavaScript engine, enforces strict mode, and is the only version that supports NetSuite's generative AI modules. Oracle expects to remove support for SuiteScript 1.0, 2.0, and scripts tagged 2.x in the NetSuite 2028.2 release, so all scripts need to run as 2.1 by then.

Key takeaways

  • SuiteScript 2.1 became the standard in 2026.2; all scripts must use 2.1 by 2028.2.
  • Scripts tagged @NApiVersion 2.x currently run as 2.0, not 2.1.
  • Every script type has a usage unit limit and a time limit; user events get 1,000 units and 300 seconds.
  • SSS_USAGE_LIMIT_EXCEEDED is usually a design problem: too much work in the wrong script type.
  • N/llm and other AI modules work only in SuiteScript 2.1 server scripts.

The deadline

The SuiteScript retirement timeline you need to plan for

Oracle has published the transition in four release steps. Support for SuiteScript 1.0, SuiteScript 2.0, and scripts annotated @NApiVersion 2.0 or @NApiVersion 2.x is expected to be removed in 2028.2.

  1. 2026.2

    SuiteScript 2.1 becomes the standard scripting model for new and existing scripts. Accounts start seeing notifications about scripts on older versions.

  2. 2027.1

    SuiteScript 1.0 enters end-of-life support, covering critical issues only. Other problems require converting the script to 2.1 first.

  3. 2028.1

    SuiteScript 1.0 scripts can no longer be deployed in new accounts. SuiteScript 2.0 and 2.x scripts run as 2.1 by default.

  4. 2028.2

    All new and existing scripts must use SuiteScript 2.1.

Source: Oracle NetSuite Help Center, Transitioning To SuiteScript 2.1. Oracle describes these dates as expected and they can change; confirm against your release notes.

The 2028.1 step is the one to watch. Once 2.0 and 2.x scripts start running on the 2.1 engine by default, any behavior differences will show up in production unless you have tested them first. Legacy scripts often run billing, inventory syncs, and month-end jobs, so the risk of waiting is discovering a broken process on Oracle's schedule instead of yours. The NetSuite 2026.2 release guide covers the wider release context.

Reference

SuiteScript script types and their governance limits

Every script runs under two ceilings: a usage unit limit and a time limit. Picking the right script type for the job is the single biggest factor in avoiding governance errors.

Script typeWhat it is forUsage units per executionTime limit
Client scriptBrowser-side validation and field behavior on forms1,000 (per script)300 seconds
User eventLogic that runs when a record is loaded, saved, or deleted1,000300 seconds
SuiteletCustom pages and tools inside NetSuite1,000300 seconds
RESTletCustom endpoints for integrations5,000300 seconds
ScheduledBackground jobs on a schedule or on demand10,0003,600 seconds
Map/reduceLarge data jobs processed in parallel stagesPer stage: input 10,000; map 1,000; reduce 5,000; summarize 10,000Per stage: 3,600 / 300 / 900 / 3,600 seconds
Mass updateCustom actions applied across many records1,000 per record300 seconds
Workflow actionCustom actions inside a SuiteFlow workflow1,000 per workflow state300 seconds
PortletCustom dashboard portlets1,000300 seconds
Custom tool (2.1 only)Custom tools for NetSuite's AI connector integrations1,000 per tool execution300 seconds
Bundle and SDF installationSetup logic when a bundle or SuiteCloud project installs10,0003,600 seconds

Source: Oracle NetSuite Help Center, Script Type Usage Unit Limits, Script Execution Time Limits, and Map/Reduce Governance. Individual API calls also consume units; each method's help topic lists its cost.

Two details catch teams out. First, a scheduled script cannot yield or set recovery points in SuiteScript 2.x, so long jobs belong in map/reduce, which yields automatically. Second, map/reduce has a 200 MB ceiling on persisted data, so passing whole records between stages instead of IDs can stop a job partway through.

Version comparison

SuiteScript 1.0 vs. 2.0 vs. 2.1

FeatureSuiteScript 1.0SuiteScript 2.0SuiteScript 2.1
StructureGlobal functions (nlapi*)Modules declared with define()Modules declared with define()
JavaScript supportOlder (ES5)Older (ES5)Modern ECMAScript features, such as arrow functions, classes, let and const
Server runtimeLegacy engineLegacy engineGraal JavaScript engine, strict mode
Script loop limit errorSSS_INSTRUCTION_COUNT_EXCEEDEDSSS_INSTRUCTION_COUNT_EXCEEDEDSSS_STATEMENT_COUNT_EXCEEDED
AI modules (N/llm and others)NoNoYes
StatusEnd-of-life support from 2027.1Runs as 2.1 by default from 2028.1Current standard
Supported untilExpected removal in 2028.2Expected removal in 2028.2Supported

Oracle states that the SuiteScript API is the same in 2.0 and 2.1, with a few exceptions such as the N/llm and N/pgp modules. The difference is the runtime: because 2.1 uses a different engine, some 2.0 code behaves differently. Oracle's help also notes two current gaps to check before you migrate: the SuiteTax Engine does not support SuiteScript 2.1, and 2.1 client scripts are not supported in the Scriptable Cart. If your account uses either, confirm Oracle's latest guidance for those scripts as part of your plan.

Step by step

How to migrate scripts to SuiteScript 2.1

For most 2.0 scripts the change itself is small. The work is in finding every script, testing it on the new engine, and rolling out safely.

  1. Inventory every script and its version

    List all script records with their @NApiVersion tag, script type, deployments, and owner. Flag business-critical scripts and anything tagged 1.0, 2.0, or 2.x. A NetSuite health check produces this inventory quickly.

  2. Retire what you no longer need

    Old accounts carry scripts nobody uses. Deleting them is cheaper than migrating them, and it reduces technical debt.

  3. Test 2.0 and 2.x scripts on the 2.1 runtime in a sandbox

    Oracle provides an account-level setting that runs 2.0 and 2.x server scripts on the 2.1 runtime for testing. Turn it on in a sandbox, run your key processes, and log every difference.

  4. Update the annotation and fix strict-mode issues

    Set @NApiVersion 2.1. The most common break is strict mode: assigning a value to an undeclared variable now throws an error. Also check loops, since the loop limit error changes to SSS_STATEMENT_COUNT_EXCEEDED.

  5. Convert SuiteScript 1.0 properly

    1.0 scripts need a real rewrite into the module structure, not an annotation change. Oracle's SuiteScript 1.0 to 2.x API map helps, but some functions have no direct equivalent.

  6. Regression test, then deploy in phases

    Test in sandbox and in your Release Preview account, deploy the lowest-risk scripts first, and monitor execution logs after each wave. Pair this with your normal release testing cycle.

Troubleshooting

Common SuiteScript errors and how to fix them

These are the errors we see most often in production NetSuite accounts. Start with the usage limit, since it causes more failed scripts than anything else.

SSS_USAGE_LIMIT_EXCEEDED

"Script Execution Usage Limit Exceeded": what it means and how to fix it

Every SuiteScript API call costs usage units, and every script type has a ceiling, such as 1,000 units for a user event or 10,000 for a scheduled script. When a script spends more than its allowance, NetSuite stops it and throws this error. In map/reduce, the limit applies to each function invocation: exceeding 1,000 units in a single map call ends that call. The error almost always means the script is doing too much work in one execution, usually by loading and saving records inside a loop.

  1. Measure it. Log runtime.getCurrentScript().getRemainingUsage() at key points to see where units go.
  2. Stop loading full records you only touch lightly. Use search.lookupFields to read a few fields and record.submitFields to update a few, instead of a full load and save.
  3. Get data from one search, not many loads. Add the fields you need as search columns, and page through large result sets with runPaged().
  4. Move bulk work to map/reduce. It splits the job into small invocations and yields automatically. A user event can hand work off by submitting a map/reduce task with the N/task module.
  5. Keep map and reduce functions small. Process one record per invocation and pass IDs, not whole records, between stages.
  6. Check what your script triggers. Records saved by scheduled and map/reduce scripts run their own user event scripts and workflows, which add time and load.
/**
 * @NApiVersion 2.1
 * @NScriptType UserEventScript
 */
define(['N/runtime', 'N/search', 'N/record', 'N/log'], (runtime, search, record, log) => {
  const afterSubmit = (context) => {
    const soId = context.newRecord.id;

    // Read a few fields without loading the whole record
    const fields = search.lookupFields({
      type: search.Type.SALES_ORDER,
      id: soId,
      columns: ['tranid', 'memo']
    });

    // Update a few fields without a full load and save
    record.submitFields({
      type: record.Type.SALES_ORDER,
      id: soId,
      values: { memo: 'Reviewed: ' + fields.tranid }
    });

    log.debug({ title: 'Units left', details: runtime.getCurrentScript().getRemainingUsage() });
  };
  return { afterSubmit };
});

Illustrative pattern only. Test in a sandbox before deploying, and note that updating the same record inside its own afterSubmit can still trigger workflows on that record.

No matching error. Try part of the code, such as LIMIT, or a keyword such as search.

SSS_TIME_LIMIT_EXCEEDED

Script ran too long

Cause: The script passed its time limit, such as 300 seconds for user events, Suitelets, and RESTlets, or 3,600 for scheduled scripts. Oracle notes that triggered user events, workflows, and slow database queries all add to run time.

Fix: Move long work to map/reduce, reduce records touched per run, and check which other scripts your saves trigger.

SSS_INSTRUCTION_COUNT_EXCEEDED / SSS_STATEMENT_COUNT_EXCEEDED

Too many operations, usually a runaway loop

Cause: The script executed more operations than allowed. SuiteScript 2.1 reports SSS_STATEMENT_COUNT_EXCEEDED; older versions report SSS_INSTRUCTION_COUNT_EXCEEDED.

Fix: Check every loop for a terminating condition that can actually be met, and avoid heavy nested loops over large arrays.

SSS_REQUEST_LIMIT_EXCEEDED

Too many concurrent RESTlet calls

Cause: Integration requests exceeded your account's concurrency limit, set by service tier and SuiteCloud Plus licenses. RESTlets return HTTP 400 with this code.

Fix: Retry with back-off, spread syncs over time, and reduce redundant calls. See why NetSuite is slow for concurrency limits by tier.

SSS_SEARCH_FOR_EACH_LIMIT_EXCEEDED

Search loop returned too many results

Cause: ResultSet.each() can iterate through up to 4,000 results.

Fix: Use search.runPaged() and loop through pages, or narrow the search with filters.

PERSISTED_DATA_LIMIT_FOR_MAPREDUCE_SCRIPT_EXCEEDED

Map/reduce stored too much data

Cause: A map/reduce job held more than 200 MB of keys and values waiting to be processed. Search results with many columns count toward it.

Fix: Return fewer columns from getInputData, pass record IDs instead of full objects, and write smaller values.

KEY_LENGTH_IS_OVER_3000_BYTES / VALUE_LENGTH_IS_OVER_10_MB

Map/reduce key or value too large

Cause: A key written in map or reduce exceeded 3,000 characters, or a value exceeded 10 MB.

Fix: Use short, simple keys such as an internal ID, and put data in values. Watch dynamically built strings.

RCRD_HAS_BEEN_CHANGED

Record changed after it was loaded

Cause: Another user, script, or workflow saved the record between your load and your save, often when an afterSubmit script loads and saves the same record.

Fix: Reload and retry, use record.submitFields for small updates, and avoid multiple saves of the same record in one process.

INSUFFICIENT_PERMISSION

Script role cannot access a record or field

Cause: Scripts run with a role's permissions. The executing role, often the triggering user's, lacks access to a record, field, or subsidiary.

Fix: Review the deployment's execution role and the role's permissions, and grant only what the script needs.

ReferenceError after moving to 2.1

Strict mode breaks old code

Cause: SuiteScript 2.1 runs in strict mode, so assigning to a variable that was never declared now throws an error.

Fix: Declare every variable with const or let, then retest the script on the 2.1 runtime in a sandbox.

SSS_MISSING_REQD_ARGUMENT / INVALID_FLD_VALUE

Bad input to an API call

Cause: A required option is missing, or a value does not match the field type, such as text in a select field or an inactive internal ID.

Fix: Validate inputs before the call, log the options object, and check field IDs against the Records Browser.

If the same errors keep coming back, the cause is usually design rather than a single bug. Our NetSuite customization services team refactors scripts to fit governance, and our NetSuite support services cover monitoring and fixes after go-live. For problems outside scripting, see top NetSuite support issues and fixes.

New in SuiteScript 2.1

AI inside SuiteScript 2.1: N/llm and related modules

This is the most forward-looking reason to move to 2.1. These modules are available only to SuiteScript 2.1 scripts.

N/llm

Sends prompts to large language models through Oracle Cloud Infrastructure (OCI) Generative AI and returns the response to your script, for summarizing, drafting, classifying, or extracting data. NetSuite provides a free monthly usage pool, with separate pools for each installed SuiteApp; adding your own OCI credentials removes that cap. It is available only in certain regions.

N/machineTranslation

Translates text through the OCI Language service. Oracle notes it supports unlimited requests without OCI credentials, making it a lower-cost option than prompting an LLM for translation.

N/documentCapture

Extracts structured data from documents such as invoices. Like N/llm, it draws on a free monthly pool, with OCI credentials available for higher volume.

Custom tool script type

A 2.1-only script type for building custom tools that AI assistants can call through NetSuite's AI connector, with a limit of 1,000 units per tool execution.

Generative AI responses vary by design, so validate outputs anywhere accuracy matters, especially in finance processes. For the bigger picture, see how AI is transforming SuiteScript development, our NetSuite MCP and AI Connector guide, and where this fits in NetSuite Next.

Integrations

Integration and authentication deadlines that affect your scripts

SuiteScript is not the only legacy technology on a timeline. If your RESTlets or integrations use older methods, three changes overlap with the SuiteScript transition:

  • Token-based authentication: from 2027.1, new REST web services and RESTlet integrations can no longer be created with TBA; OAuth 2.0 is the standard.
  • NLAuth: reported as no longer supported for integrations from 2027.1.
  • SOAP web services: Oracle states SOAP will no longer be available from 2028.2, the same release as the SuiteScript cutoff, and existing SOAP integrations will stop working.

Because these deadlines touch the same scripts and integrations, plan them together. Our TBA to OAuth 2.0 migration guide covers the authentication side, and why NetSuite integrations fail covers common breakpoints. Scripts always run within a role's permissions, so pair any migration with a role review.

Two deadlines, one plan

EPIQ Infotech, an Oracle NetSuite Alliance Partner since 2013, inventories your scripts, migrates SuiteScript 1.0, 2.0, and 2.x code to 2.1 with sandbox testing, fixes scripts that hit governance limits, and moves integrations to OAuth 2.0 in the same project. See the full scope of our NetSuite support services.

FAQ

SuiteScript 2.x: frequently asked questions

When will SuiteScript 1.0 and 2.0 stop working?

Oracle expects to remove support for SuiteScript 1.0, SuiteScript 2.0, and scripts annotated 2.0 or 2.x in the NetSuite 2028.2 release. SuiteScript 1.0 enters end-of-life support in 2027.1, and from 2028.1, 2.0 and 2.x scripts run as 2.1 by default.

What is the difference between SuiteScript 2.0 and 2.1?

The SuiteScript API is the same in both, with a few exceptions such as the N/llm module. SuiteScript 2.1 runs on a newer JavaScript engine with strict mode and modern language features, so some 2.0 code behaves differently and needs testing after the switch.

Do scripts annotated @NApiVersion 2.x run as SuiteScript 2.1?

Not yet. Oracle's documentation states that the 2.x value currently means SuiteScript 2.0. From 2028.1, 2.0 and 2.x scripts are expected to run as 2.1 by default, so test them on the 2.1 runtime before then.

What does SSS_USAGE_LIMIT_EXCEEDED mean?

It means a script used more usage units than its script type allows, such as 1,000 for a user event or 10,000 for a scheduled script, so NetSuite stopped it. The usual fix is to stop loading records in loops, use lookupFields and submitFields for small reads and writes, and move bulk work to map/reduce.

How do I check how many usage units a script has left?

Call runtime.getCurrentScript().getRemainingUsage() from the N/runtime module and log the result at key points in your script. It returns the units remaining for the current execution.

What are the governance limits for a user event script?

A user event script can use up to 1,000 usage units and run for up to 300 seconds per execution. Oracle also advises keeping user event scripts responsive, because they run while users wait for records to load or save.

Is the N/llm module free to use?

NetSuite provides a free monthly usage pool for N/llm requests, tracked on the AI Preferences page. For more volume, you can connect your own Oracle Cloud Infrastructure account with the OCI Generative AI service. N/llm works only in SuiteScript 2.1 and is available in certain regions.

How long does a SuiteScript 2.1 migration take?

It depends on how many scripts you have, how many are on 1.0, and how critical they are. A few 2.0 scripts can move quickly, while a mature account needs an inventory, sandbox testing on the 2.1 runtime, and a phased rollout. Starting now leaves time before the 2028.1 default switch.

Santosh K

Santosh Krishnamoorthy is a Principal ERP Consultant at EPIQ Infotech, with extensive experience in NetSuite and enterprise systems. He works with finance and operations teams to improve reporting accuracy, streamline workflows, and build ERP environments that support sustainable growth. His writing focuses on practical insights drawn from real implementation and support experience.

Free Consultation

Talk to a NetSuite Expert

Response within 1 hour

Blogs Form

What do you think?

Related articles

Contact us

Have questions? We're here to listen.

We’re happy to answer any questions you may have and help you determine which of our services best fit your needs.

Your benefits:
What happens next?
1

We Schedule a call at your convenience 

2

We do a discovery and consulting meeting

3

We prepare a proposal 

Schedule a Free Consultation
By providing a telephone number and submitting this form you are consenting to be contacted by SMS text message. Message & data rates may apply. You can reply STOP to opt-out of further messaging.