SSS_USAGE_LIMIT_EXCEEDED: You have exceeded the governance on SuiteScript usage of this API.Quick Reference
- Error Code
- SSS_USAGE_LIMIT_EXCEEDED
- Severity
- high
- Type
- script
- Versions
- 2024.1, 2024.2, 2025.1, 2025.2, 2026.1
Why This Happens
- Calling record.load() or record.save() inside a loop without batching
- Running N+1 searches — one search per record instead of a single filtered search
- Using a Scheduled Script when a Map/Reduce script is required for the data volume
- Loading full records when only a few field values are needed (use record.submitFields or lookupFields instead)
- Calling nlapiRequestURL or https.get in tight loops without throttling
How to Fix It
Step 1: Identify the expensive API call
Open the script in the SuiteScript Debugger or add log.audit calls before each API operation. The governance cost of each API is listed in NetSuite Help under 'SuiteScript 2.x API Governance'. Common culprits: record.load (10 units), record.save (20 units), search.run().each (10 units per search), https.get (10 units).
Step 2: Move record loads out of loops
If you're calling record.load() inside a for/while/each loop, refactor to use search.lookupFields() (5 units) or a single saved search that returns all the data you need in one call. For bulk updates, use record.submitFields() (10 units) instead of load + setValue + save (30 units).
Step 3: Switch to Map/Reduce for large datasets
Map/Reduce scripts get 10,000 governance units per invocation of map() and reduce(), and they automatically yield and resume. If your Scheduled Script processes more than ~200 records, Map/Reduce is almost always the right choice. Use the getInputData stage for your search, and map() for per-record processing.
Step 4: Implement governance checkpoints
In Scheduled Scripts, check runtime.getCurrentScript().getRemainingUsage() before each expensive operation. If remaining units are below a threshold (e.g., 500), reschedule the script with task.create and pass a bookmark parameter so it resumes where it left off.
Code Example
/**
* @NApiVersion 2.1
* @NScriptType ScheduledScript
*/
define(['N/runtime', 'N/search', 'N/record', 'N/task'], (runtime, search, record, task) => {
const GOVERNANCE_THRESHOLD = 500;
function execute(context) {
const script = runtime.getCurrentScript();
const lastId = script.getParameter({ name: 'custscript_last_processed_id' }) || 0;
const results = search.create({
type: search.Type.SALES_ORDER,
filters: [['internalidnumber', 'greaterthan', lastId]],
columns: ['internalid', 'entity', 'total']
}).run();
let processedId = lastId;
results.each((result) => {
// Check governance BEFORE the expensive operation
if (script.getRemainingUsage() < GOVERNANCE_THRESHOLD) {
log.audit('Rescheduling', `Pausing at ID ${processedId}`);
reschedule(processedId);
return false; // stop iteration
}
// Your per-record logic here
record.submitFields({
type: record.Type.SALES_ORDER,
id: result.id,
values: { memo: 'Processed' }
});
processedId = result.id;
return true; // continue
});
}
function reschedule(lastId) {
task.create({
taskType: task.TaskType.SCHEDULED_SCRIPT,
scriptId: runtime.getCurrentScript().id,
deploymentId: runtime.getCurrentScript().deploymentId,
params: { custscript_last_processed_id: lastId }
}).submit();
}
return { execute };
});Common Mistakes
- Catching the error and retrying the same operation — you'll hit the limit again immediately
- Setting the governance threshold too low (e.g., 50 units) — a single record.save costs 20 units, so you need headroom
- Forgetting that search.run().each() itself costs 10 units per search, not per result
- Using record.load + record.save when record.submitFields would do the job at 1/3 the governance cost
Alternative Approaches
- Use SuiteQL (query.runSuiteQL) for read-only data — it costs only 10 units regardless of result count, versus 10 units per search.create
- For very large datasets (100K+ records), consider a CSV import via task.create with TaskType.CSV_IMPORT instead of scripted record operations
- Use N/record submitFields for field-only updates — 10 units vs 30 for load+save