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.
By Santosh Krishnamoorthy, Principal ERP Consultant, EPIQ Infotech. First published April 25, 2025. Updated October 14, 2026 against Oracle's NetSuite Help Center.
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.xcurrently 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.
- 2026.2
SuiteScript 2.1 becomes the standard scripting model for new and existing scripts. Accounts start seeing notifications about scripts on older versions.
- 2027.1
SuiteScript 1.0 enters end-of-life support, covering critical issues only. Other problems require converting the script to 2.1 first.
- 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.
- 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 type | What it is for | Usage units per execution | Time limit |
|---|---|---|---|
| Client script | Browser-side validation and field behavior on forms | 1,000 (per script) | 300 seconds |
| User event | Logic that runs when a record is loaded, saved, or deleted | 1,000 | 300 seconds |
| Suitelet | Custom pages and tools inside NetSuite | 1,000 | 300 seconds |
| RESTlet | Custom endpoints for integrations | 5,000 | 300 seconds |
| Scheduled | Background jobs on a schedule or on demand | 10,000 | 3,600 seconds |
| Map/reduce | Large data jobs processed in parallel stages | Per stage: input 10,000; map 1,000; reduce 5,000; summarize 10,000 | Per stage: 3,600 / 300 / 900 / 3,600 seconds |
| Mass update | Custom actions applied across many records | 1,000 per record | 300 seconds |
| Workflow action | Custom actions inside a SuiteFlow workflow | 1,000 per workflow state | 300 seconds |
| Portlet | Custom dashboard portlets | 1,000 | 300 seconds |
| Custom tool (2.1 only) | Custom tools for NetSuite's AI connector integrations | 1,000 per tool execution | 300 seconds |
| Bundle and SDF installation | Setup logic when a bundle or SuiteCloud project installs | 10,000 | 3,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
| Feature | SuiteScript 1.0 | SuiteScript 2.0 | SuiteScript 2.1 |
|---|---|---|---|
| Structure | Global functions (nlapi*) | Modules declared with define() | Modules declared with define() |
| JavaScript support | Older (ES5) | Older (ES5) | Modern ECMAScript features, such as arrow functions, classes, let and const |
| Server runtime | Legacy engine | Legacy engine | Graal JavaScript engine, strict mode |
| Script loop limit error | SSS_INSTRUCTION_COUNT_EXCEEDED | SSS_INSTRUCTION_COUNT_EXCEEDED | SSS_STATEMENT_COUNT_EXCEEDED |
| AI modules (N/llm and others) | No | No | Yes |
| Status | End-of-life support from 2027.1 | Runs as 2.1 by default from 2028.1 | Current standard |
| Supported until | Expected removal in 2028.2 | Expected removal in 2028.2 | Supported |
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.
Inventory every script and its version
List all script records with their
@NApiVersiontag, 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.Retire what you no longer need
Old accounts carry scripts nobody uses. Deleting them is cheaper than migrating them, and it reduces technical debt.
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.
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.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.
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.
"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.
- Measure it. Log
runtime.getCurrentScript().getRemainingUsage()at key points to see where units go. - Stop loading full records you only touch lightly. Use
search.lookupFieldsto read a few fields andrecord.submitFieldsto update a few, instead of a full load and save. - Get data from one search, not many loads. Add the fields you need as search columns, and page through large result sets with
runPaged(). - 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.
- Keep map and reduce functions small. Process one record per invocation and pass IDs, not whole records, between stages.
- 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Related NetSuite resources

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


