NetSuite Custom Records for WooCommerce at a Glance
- Three tiers, cheapest first: a custom list for fixed dropdown values, a custom field on a native record for one more data point, a custom record only when the data has its own lifecycle.
- Governance units run the other way from what most teams assume: a custom record.load() costs 2 units versus 10 for a transaction record — the expensive part of a custom record is setup, never runtime.
- Every custom record type needs Access Type set to “Use Permission List” and a Permissions subtab configured, or role access silently defaults to nothing.
- Document the schema outside of NetSuite too — tribal knowledge in custom records is the most common integration handoff failure.
Custom records are one of NetSuite’s most powerful features for integrators — and one of the most overused. WooCommerce data doesn’t always map cleanly onto native NetSuite record types, and when it doesn’t, a custom record can genuinely be the right tool. The problem is teams reaching for a full custom record as a default rather than checking the two cheaper options first, creating maintenance debt that outlives the person who built it. This guide, part of the NetSuite + WooCommerce integration guide library, covers the three-tier decision, the governance-unit cost most teams never check, and the permission settings a new custom record type actually needs.
Ask These Three Questions First
Before creating a custom record for anything coming out of WooCommerce, rule out the cheapest option first: if the data is nothing but a fixed set of selectable values — an order source, a custom status, a fulfillment reason code — that’s a custom list, not a custom record. Oracle’s own documentation describes a custom list as exactly that: a list of values used in custom fields on forms and records, with no independent permissions, search, or scripting surface of its own. Once a list is ruled out, run the sequence below.
1. Does a native record type already cover this?
Product variations, customer groups, order metadata, and most WooCommerce concepts have a reasonable native NetSuite equivalent — item, customer category, custom fields on sales order — even if it’s not a perfect semantic match. Native record types get better platform support, SuiteQL access, and don’t need custom permissions configured from scratch.
2. Can a custom field on a native record solve it instead? A custom record is justified when you have a genuinely separate entity with its own lifecycle — think WooCommerce subscription plans, loyalty point ledgers, or batch/lot metadata. If what you actually need is “one more piece of data attached to an order,” that’s a custom field on Sales Order, not a new record type.
3. Will this need its own search, workflow, and permission set? If the answer is yes across the board, you’re building something closer to a mini-application inside NetSuite, and a custom record is the right call — just budget the ongoing maintenance accordingly, covered with real numbers below.
When Custom Records Are the Right Call
| WooCommerce concept | Cheaper tier fits? | Recommendation |
|---|---|---|
| Product variations | Yes — matrix items | Use native matrix item functionality |
| Order source / status labels | Yes — fixed values | Custom list feeding a custom field, not a record |
| Batch/lot tracking | Partial — inventory detail is limited | Custom record often justified for full lot metadata (expiry, recall status) |
| Loyalty points ledger | No native equivalent | Custom record is the right tool |
| Order-level custom metadata | Yes — custom fields on Sales Order | Use custom fields, not a separate record |
| Subscription plan definitions | Partial, depends on billing bundle | Custom record if not using a subscription management SuiteApp |
Verdict: a custom record earns its place only for data with an independent lifecycle — a loyalty ledger, a lot table, a subscription plan. Everything else in this table is cheaper as a list, a field, or a native record.
The Governance Cost Nobody Budgets For
Most teams assume a custom record is expensive to touch from SuiteScript. Oracle’s own SuiteScript 2.1 API Governance table says the opposite: custom records are the cheapest record class to operate on, because they carry none of the accounting and posting logic a transaction record does.
| Operation | Custom record | Standard non-transaction record | Transaction record |
|---|---|---|---|
| record.load() | 2 units | 5 units | 10 units |
| record.save() | 4 units | 10 units | 20 units |
| record.delete() | 4 units | 10 units | 20 units |
| record.submitFields() | 2 units | 5 units | 10 units |
Verdict: a custom record.load() costs 5x less than the same call against a transaction record (2 units versus 10). According to Oracle’s governance documentation, “custom records require less processing than standard records, therefore, the usage unit cost for custom records is lower than for standard records.” The real cost of a custom record was never the runtime — it’s the one-time setup: permissions, search, and documentation, covered next.
The Permission Model You’re Actually Building
A native NetSuite record ships with role permissions already wired into the platform. A custom record type does not — you build that from a blank page, and it’s easy to get wrong. Oracle’s documentation on setting up permissions for a custom record type specifies the mechanism precisely: Access Type must be set to “Use Permission List” for anything on the Permissions subtab to take effect at all. Leave it on the default and the subtab does nothing.
Once “Use Permission List” is selected, each role gets a Level — None, View, Create, Edit, or Full — plus an optional Restrict setting that limits a role to records it created (“Viewing and Editing”) or lets it view everything but edit only its own (“Editing Only”). The detail teams miss: permission settings restrict access to record entries, not the record type itself — a role still needs separate permission to the custom record type generally, or the Permissions subtab settings never take effect no matter how they’re configured.
Beyond permissions, every custom record needs its own saved searches or SuiteQL views maintained as reporting needs evolve — custom records are queryable through SuiteQL and searchable through saved searches the same as native records, so the tradeoff is entirely setup work, not reporting capability. It also needs its own place in your integration’s error handling: a custom record write failure doesn’t get the same built-in retry and logging behavior a native record transaction does unless you build it yourself. Multiply this by however many custom records accumulate over a few years — the same governance math that makes each individual record cheap to touch (see above) has nothing to do with how expensive the accumulated schema gets to maintain, the way governance costs pile up for unbounded SuiteScript loops covered in this breakdown of SuiteScript governance budgets — and you end up with a shadow schema only the original developer fully understands.
Undocumented custom records are the number one handoff failure.
When an integration partner or employee who built a custom record leaves, the next person often doesn’t know it exists, what it’s for, or which integration jobs read and write to it — until something breaks. Keep a living document (outside of NetSuite, in your team wiki or repo) listing every custom record, its purpose, and which sync jobs touch it. The checklist below turns that into something you can actually run.
- List every custom record type in the account (Customization > Lists, Records, & Fields > Record Types) with its owner.
- Confirm each type’s Access Type is “Use Permission List” and the Permissions subtab matches least-privilege, not whoever configured it first.
- Verify a saved search or SuiteQL view exists for each type that reporting or support actually relies on.
- Document which integration jobs read or write each custom record — the job name, not just “the sync.”
- Confirm error handling exists for writes to each custom record, matching the alerting a failed Sales Order write gets.
- Record the record’s purpose and owner outside NetSuite — a wiki page or repo file, not only the record’s own description field.
- Re-run this audit at the next NetSuite release upgrade — a record built for last year’s workflow can silently drift from this year’s defaults.
The Practical Default
Start every new WooCommerce-to-NetSuite data mapping decision at the cheapest tier: a custom list for fixed values, a custom field for one more data point on an existing record, and a custom record only when the data has its own lifecycle, its own permissions requirements, or its own reporting needs a native record genuinely cannot support. Document it the moment you create it, not after the fact — the governance units are the part that was never expensive; the audit trail is.
Building this mapping from scratch across a full WooCommerce-to-NetSuite sync — not just the custom record layer — is exactly what NetSuite Integration Pro is built to handle: the native-record mappings, the custom-field layer, and the sync jobs that write to whichever tier the data actually needs.
Get the working checklists
The runbooks and decision checklists from these guides, as printable PDFs — free in the SoftXone guide library.
References
- NetSuite Applications Suite — SuiteScript 2.1 API GovernanceOracle NetSuite Help — governance unit costs for record.load, record.save, record.delete, and record.submitFields by record class.
- NetSuite Applications Suite — Setting Up a Permissions List for a Custom Record TypeOracle NetSuite Help — Access Type, the Permissions subtab, and the Level/Restrict options for a custom record type.
- NetSuite Applications Suite — Custom ListOracle NetSuite Help — custom lists as a lighter-weight alternative to a custom record for fixed dropdown values.
- Oracle SuiteQL OverviewNetSuite SuiteQL reference for querying native vs custom record data.
Frequently asked questions
What is the difference between a custom record and a custom list in NetSuite?
A custom list stores only a fixed set of selectable values for use in dropdown fields, with no independent permissions, search, or scripting surface. A custom record is a full data structure with its own fields, permissions, and SuiteScript CRUD support. Reach for a list when the requirement is “pick one of these values,” and a record only when the data needs its own lifecycle.
Do custom records cost more governance units than native records?
No — the opposite. Oracle’s SuiteScript governance model charges 2 units for a custom record.load() versus 10 units for a transaction record, and 4 units for record.save() versus 20, because custom records carry none of the accounting logic native transaction records post. The real cost of a custom record is the one-time setup work: permissions, search, and documentation.
What permission settings does a new custom record type need?
Set Access Type to “Use Permission List,” then configure the Permissions subtab with a Level — None, View, Create, Edit, or Full — per role. Permission settings restrict which record entries a role can see or edit; the role also needs separate permission to the custom record type itself, or the settings never take effect.
How do I stop a custom record from becoming an undocumented liability?
Document the record’s purpose, owner, and every integration job that reads or writes it somewhere outside NetSuite — a wiki page or a repo file, not the record’s own description field — the moment it’s created, and re-audit it at every NetSuite release upgrade.
Can custom records participate in SuiteQL queries the same way native records do?
Yes. Custom records are queryable through SuiteQL and searchable through saved searches the same as native records — the tradeoff of choosing a custom record is entirely in setup and permissions overhead, not in query or reporting capability.

Leave a Reply