Introduction
In large-scale NetSuite environments, managing thousands of custom records manually isn’t just time-consuming—it’s inefficient. Fortunately, SuiteScript offers a powerful solution: the Map/Reduce script type, built for batch processing with performance and governance in mind.
Whether you’re updating custom statuses, recalculating fields, or syncing datasets, this script type is your go-to for scalable, server-side automation.
Why Use Map/Reduce?
Compared to other SuiteScript types like Scheduled or User Event scripts, Map/Reduce is purpose-built for:
- High-volume operations with built-in governance handling
- Parallel record processing, increasing throughput
- Robust error handling through a summarize() stage
- Seamless integration with Saved Searches and external data sources
Understanding the Architecture
In a Map/Reduce script, the getInputData() stage is responsible for defining the input source—this could be a saved search, a static array, or a data set pulled from another system. For example, you might use it to retrieve all custom records where the status is not marked as “Processed.” Next, the map () stage handles the individual processing of each record, such as updating the status field one by one. The optional reduce () stage comes into play when you need to aggregate or group data—for instance, summing values or consolidating related records. Finally, the summarize () stage takes care of final logging, reporting any errors that occurred during execution, and providing a summary of governance usage, helping ensure transparency and traceability of the entire process.
Practical Use Case
Scenario: You need to update the field “custrecord_status” on all “customrecord_myrecord” entries that are not yet marked as “Processed”.
Why Map/Reduce?
- Handles thousands of records
- Automatically manages governance units
- Offers retry and error logging in the summarize() stage
Sample Code
/**
* @NApiVersion 2.1
* @NScriptType MapReduceScript
*/
define(['N/search', 'N/record', 'N/log'], (search, record, log) => {
const getInputData = () => {
return search.create({
type: 'customrecord_myrecord',
filters: [['custrecord_status', 'isnot', 'Processed']],
columns: ['internalid']
});
};
const map = (context) => {
const result = JSON.parse(context.value);
try {
record.submitFields({
type: 'customrecord_myrecord',
id: result.id,
values: { custrecord_status: 'Processed' }
});
log.audit('Updated Record', `ID: ${result.id}`);
} catch (e) {
log.error(`Failed to update Record ID ${result.id}`, e.message);
}
};
const summarize = (summary) => {
log.audit('Execution Summary', `Total usage: ${summary.usage}`);
summary.output.iterator().each((key, value) => {
log.audit(`Map Output`, `${key}: ${value}`);
return true;
});
summary.errors.iterator().each((key, error) => {
log.error(`Error with key ${key}`, error.message);
return true;
});
};
return { getInputData, map, summarize };
});
Best practices
Start with test data or a limited saved search
Use submitFields() for small field updates—it’s faster than load() and save()
Keep map () logic light to prevent timeouts
Log extensively in summarize () for traceability
Monitor governance usage and scale intelligently
Final Thoughts
If you’re managing high-volume updates, SuiteScript’s Map/Reduce script is the most powerful and scalable tool in your arsenal. With the right implementation and governance awareness, mass updating thousands of records can be safe, efficient, and fully automated.