SuiteScript 2.x and Its Entry Points
The four script types you will use most, when each of them runs, and why choosing the wrong one makes your logic feel like it never executes.
SuiteScript is JavaScript that NetSuite runs at particular moments. Those moments are entry points, and each script type has its own. The most common mistake is not in the logic but in picking a script type that never activates at the moment you had in mind.
The types you will use most
| Type | Runs in | Main entry points |
|---|---|---|
| Client Script | The browser, as the user fills a form | pageInit, fieldChanged, saveRecord |
| User Event | The server, as a record is saved | beforeLoad, beforeSubmit, afterSubmit |
| Suitelet | The server, when a custom page is opened | onRequest |
| Map/Reduce | The server, for large volumes of data | getInputData, map, reduce, summarize |
| Scheduled Script | The server, on a schedule | execute |
| RESTlet | The server, called by an outside system | get, post, put, delete |
Choosing between beforeSubmit and afterSubmit
beforeSubmit runs before the data is written — this is where validation and field changes belong, because the changes are saved without needing an extra save. afterSubmit runs once the record is stored and has an ID — this is where you create other records, send email, or call an outside system.
define(['N/error'], (error) => {
const beforeSubmit = (context) => {
if (context.type === context.UserEventType.DELETE) return;
const rec = context.newRecord;
const total = rec.getValue({ fieldId: 'total' });
if (total <= 0) {
throw error.create({
name: 'INVALID_TOTAL',
message: 'Transaction total must be greater than zero.',
notifyOff: true
});
}
};
return { beforeSubmit };
});For processing many records, Map/Reduce is almost always the right choice over a Scheduled Script. Not because it is faster, but because of governance: Map/Reduce splits the work into small pieces and remembers its progress, so it does not die halfway once the data volume grows.