Custom-record field definitions show up in two places developers reach for constantly: SuiteQL analytics metadata and SuiteCloud / SDF object XML. They answer related questions with different tools, identifiers and failure modes.
This comparison keeps each channel in its lane. For SuiteQL discovery, see How to Query NetSuite Custom Record Fields With SuiteQL. For XML import, see SuiteCloud: Import a Custom Record and Its Custom Fields.
Side-by-side
| Concern | SuiteQL metadata | SuiteCloud / SDF XML |
|---|---|---|
| Primary use | Runtime inventory, reports, integrations | Source control, deploy, project objects |
| Authority for IDs | Records Catalog (SuiteScript and REST Query API channel) | Object XML and SuiteCloud project tools |
| Typical entry points | CustomRecordCustomField, type metadata when available |
<customrecordtype>, nested <customrecordcustomfield> |
| Availability | Account-, feature-, role- and channel-specific | Depends on account access and object:import / project setup |
| Good at | Querying what the live account exposes to analytics | Capturing deployable definitions for a script ID |
| Poor at | Guaranteeing the same shape as SDF | Acting as a SuiteQL schema reference |
Neither channel is a full substitute for the other. Neither is a query of instance data on customrecord_... records.
What SuiteQL metadata is
When the analytics schema exposes them, records such as CustomRecordCustomField return definition rows: script IDs, labels, types and relationships confirmed in the Records Catalog.
SELECT
field_definition.id,
field_definition.scriptid,
field_definition.label
FROM
CustomRecordCustomField field_definition
ORDER BY
field_definition.scriptid
Those record and column names are illustrative until verified in your catalog. The record is not universally available. Diagnosis: Why CustomRecordCustomField Is Missing From SuiteQL.
SuiteQL metadata is ideal when you need:
- A live field inventory under a service role
- Filtered lists for one custom-record type
- Automated data dictionaries: Export a NetSuite Custom-Field Data Dictionary With SuiteScript
What SuiteCloud XML is
SuiteCloud object import pulls the custom record type into the project as XML. Oracle’s custom record type XML documentation describes these as SDF project objects. Field definitions appear as nested elements, not as SuiteQL rows:
suitecloud object:import --type customrecordtype --scriptid customrecord_example --destinationfolder /Objects
<customrecordtype scriptid="customrecord_example">
<customrecordcustomfields>
<customrecordcustomfield scriptid="custrecord_example_status">
<fieldtype>SELECT</fieldtype>
<label>Status</label>
<storevalue>T</storevalue>
<selectrecordtype>-XXX</selectrecordtype>
</customrecordcustomfield>
</customrecordcustomfields>
</customrecordtype>
Oracle’s documentation on importing account components into SuiteCloud projects notes that an imported component with the same script ID overwrites the project component. Review the diff before committing.
XML is ideal when you need:
- Deployable object definitions
- Diffs between sandbox and project source
- Nested field attributes exactly as SDF models them
Naming traps
| You see | Do not assume |
|---|---|
XML element customrecordcustomfield |
SuiteQL record CustomRecordCustomField is available |
XML tag selectrecordtype |
The same string is a SuiteQL column ID |
| UI label “Record Type” | A SuiteQL field or join with that label |
| SuiteScript record field ID | An analytics field ID |
Always re-resolve SuiteQL identifiers in the Records Catalog: How to Find SuiteQL Table and Field Names.
Choosing a path
Prefer SuiteQL when
- The consumer is a script, REST query client or workbook-style analytics process
- You need to filter, join and export many definitions under role-aware access
- You are building operational documentation from the live account
Prefer SuiteCloud XML when
- The consumer is an SDF project and deployment pipeline
- You need attributes that exist in the object model but are not exposed to SuiteQL in your account
- You are moving or versioning a known
customrecord_...script ID
Use both when
- SuiteQL provides the inventory, and XML provides deployable source for selected types
- You must reconcile a list/record target that analytics returns only as a coded ID: How to Find a Custom Field’s List or Record Type With SuiteQL
Definition layers versus instance data
A third layer sits underneath both tools: instance values.
| Layer | Example question |
|---|---|
| SuiteQL metadata | Which fields are defined on this type? |
| SuiteCloud XML | How is this type represented as an SDF object? |
| Instance SuiteQL / SuiteScript | What status is stored on record 123? |
SELECT
custom_record.id,
custom_record.custrecord_example_status
FROM
customrecord_example custom_record
That query never replaces a metadata inventory or an SDF definition file.
Practical decision checklist
- Is the output a deployable project object? → SuiteCloud XML.
- Is the output a report or integration payload from the live account? → SuiteQL + Records Catalog.
- Is the analytics record missing under the execution role? → Diagnose catalog availability; fall back to XML or UI only for documentation, not as fake SuiteQL.
- Are you documenting list targets? → Prefer catalog-confirmed SuiteQL columns; cross-check XML when analytics is incomplete.
- Are you reading user-entered values? → Instance tables, not metadata and not SDF.
Related join and column detail for the analytics path:
- CustomRecordCustomField SuiteQL column reference
- How to Join CustomRecordCustomField to CustomRecordType
- NetSuite Custom Field Metadata Tables Explained
Treat SuiteQL and SuiteCloud XML as parallel projections of custom-record configuration. Translate between them deliberately; never paste one schema into the other and expect it to run.