SSS_USAGE_LIMIT_EXCEEDED — what it means and how to fix it
SSS_USAGE_LIMIT_EXCEEDED: It means your SuiteScript consumed more governance units than its script type allows — each API call costs units, and the running total crossed the ceiling. Fix it by using cheaper APIs, processing fewer records per execution, and yielding or moving bulk work to a Map/Reduce script.
When you see this
- A SuiteScript fails partway through with SSS_USAGE_LIMIT_EXCEEDED, often after processing many records successfully first.
- The script works on a small data set in the debugger but fails in production against real volume.
- A user event, scheduled, or Map/Reduce script loads or saves records inside a loop and the per-call unit cost adds up past the limit.
Causes
- The script's cumulative usage units exceeded the ceiling for its script type — for example 1,000 units for a client, user event, or Suitelet script, or 10,000 for a scheduled or Map/Reduce script.
- Expensive APIs called inside a loop — record.load (5 units) and record.save (20 units) on every iteration burn the budget fast over hundreds of records.
- Bulk work placed in a synchronous context (a user event or Suitelet, capped at 1,000 units) instead of an asynchronous, governance-friendly Map/Reduce script.
- No yielding — a long scheduled script runs straight to the unit limit instead of checking remaining usage and rescheduling itself before it runs out.
Fix
Find what is spending the units, make each operation cheaper, then yield or move the bulk work to a context built for it.
- Read the execution log to see which line raised the error — that API call is the one that pushed cumulative usage over the limit. Note how many records had already processed before it failed.
- Instrument the script with getRemainingUsage() at the top of each loop iteration to find the real unit hog, then optimise that call first.
var script = runtime.getCurrentScript(); log.debug({ title: 'usage', details: script.getRemainingUsage() }); - Replace expensive calls with cheaper equivalents: search.lookupFields (1 unit) instead of record.load (5) to read a few fields, and record.submitFields (10) instead of record.load + record.save (25) to update them.
- For anything iterating over more than a few hundred records, refactor to a Map/Reduce script — each key is processed with its own governance allowance and the framework yields and resumes automatically between stages.
- In a scheduled script that must stay scheduled, guard the loop: when getRemainingUsage() falls below the cost of one more iteration, reschedule the script with N/task and exit cleanly so the next run continues the work.
if (script.getRemainingUsage() < 100) { task.create({ taskType: task.TaskType.SCHEDULED_SCRIPT, scriptId: script.id, deploymentId: script.deploymentId }).submit(); return; }
Prevent it
- Budget every script: know its script type's unit ceiling and the cost of each API it calls, and design the workload to fit inside it.
- Default to the cheapest API that does the job — getValue/lookupFields over load, submitFields over load-then-save — and never load a full record just to read one field.
- Use Map/Reduce for any bulk or iterative job; it is the context NetSuite built for governance-heavy work.
- In scheduled scripts, always check getRemainingUsage() and reschedule before the budget runs out, so a larger data set never trips the limit.
SuiteScript version note: The governance model and per-API unit costs are identical in SuiteScript 2.0 and 2.1. SuiteScript 1.0 enforced a comparable but separately-counted usage limit; the fix strategy — cheaper calls, yielding, Map/Reduce — is the same in spirit.
Frequently asked questions
- What is the usage limit for my script type?
- Client, user event, Suitelet, portlet and workflow action scripts get 1,000 units; RESTlet scripts 5,000; scheduled and Map/Reduce scripts 10,000. Each API call deducts a set number of units from that budget.
- Does Map/Reduce remove governance limits?
- No, but it changes the maths: each key is processed with its own governance allowance and the framework yields and resumes automatically between stages, so large volumes no longer hit a single ceiling.
- Why does it only fail on large data sets?
- Usage is cumulative within one execution. A handful of records stays under the limit; the same code over thousands of records keeps adding units until it crosses the ceiling and throws.
Last reviewed: by Wouter Nortje, CA