> For the complete documentation index, see [llms.txt](https://docs.coupler.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.coupler.io/sources/category/sales/netsuite/best-practices.md).

# Best Practices

## Recommended setup

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Use Objects for standard records</strong></td><td>Choose <strong>Objects</strong> when you need a standard or custom record type as-is — invoices, sales orders, vendor bills, and similar records map cleanly to a single table this way.</td></tr><tr><td><strong>Use SuiteQL for joins and custom filters</strong></td><td>Choose <strong>SuiteQL</strong> when you need fields from multiple related records in one row, calculated columns, or filters that aren't exposed as Object parameters.</td></tr><tr><td><strong>Scope the Access Token role to what's needed</strong></td><td>Create a role for the Access Token that grants view access only to the record types your data flows actually use, rather than reusing an Administrator token. This limits blast radius if the token is ever exposed.</td></tr><tr><td><strong>Confirm Token-Based Authentication is enabled before troubleshooting</strong></td><td>Most first-time connection failures trace back to Token-Based Authentication or REST Web Services not being enabled under SuiteCloud features, or an Access Token created under the wrong role.</td></tr></tbody></table>

## Data refresh and scheduling

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Use Start date for incremental objects</strong></td><td>For record types that support it (those with a last-modified field), set <strong>Start date</strong> to pull only recently changed records instead of re-exporting the entire object every run.</td></tr><tr><td><strong>Daily refresh for most transactional data</strong></td><td>Invoices, sales orders, and vendor bills are typically entered during business hours — a daily refresh after close of business captures the day's activity.</td></tr><tr><td><strong>Full-refresh objects don't need frequent scheduling</strong></td><td>Record types without a last-modified field re-pull in full every run regardless of schedule. For large ones, refresh less frequently to reduce load and run time.</td></tr><tr><td><strong>SuiteQL always runs full</strong></td><td>SuiteQL has no incremental mode — build the date filter into your query's <code>WHERE</code> clause if you want to limit each run's scope.</td></tr></tbody></table>

## Performance optimization

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Lower Window in days for large objects</strong></td><td>Objects with a high transaction volume (e.g., Invoice, Journal Entry) can time out with the default 30-day window. Reduce <strong>Window in days</strong> to page through smaller date slices.</td></tr><tr><td><strong>Increase Window in days for small objects</strong></td><td>For low-volume record types, a larger window reduces the number of API round trips and speeds up the sync.</td></tr><tr><td><strong>Filter and aggregate inside the SuiteQL query</strong></td><td>SuiteQL is capped at 100,000 rows per query. Narrow the <code>WHERE</code> clause or aggregate (e.g., <code>SUM</code>, <code>GROUP BY</code>) in the query itself rather than pulling raw rows and aggregating downstream.</td></tr><tr><td><strong>Split one large custom record set across flows</strong></td><td>If a single Object or SuiteQL query is consistently slow or times out, split it into multiple data flows by date range or subsidiary and combine the results with Append.</td></tr></tbody></table>

## Dashboard accuracy

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>Match Access Token role across environments</strong></td><td>If you maintain separate production and sandbox data flows, make sure both Access Tokens use roles with equivalent permissions — otherwise sandbox exports may be missing objects that production has.</td></tr><tr><td><strong>Verify record types support the fields you expect</strong></td><td>Custom record types vary in which fields they expose. Run an Object once and check the output columns before building downstream transformations or dashboards on it.</td></tr><tr><td><strong>Reconcile against NetSuite for one period first</strong></td><td>Before scheduling a recurring flow, compare totals from a SuiteQL query or Object export against the equivalent NetSuite saved search or report for one period to confirm filters and date logic match.</td></tr></tbody></table>

## Common pitfalls to avoid

{% columns %}
{% column %}
**Do**

* Scope the Access Token's role to only the records you need
* Use Start date on objects that support incremental sync
* Aggregate and filter inside SuiteQL queries to stay under the row cap
* Save the Consumer Secret and Token Secret immediately when NetSuite generates them
  {% endcolumn %}

{% column %}
**Don't**

* Don't assume Start date filters every object — records without a last-modified field always sync in full
* Don't expect SuiteQL to return more than 100,000 rows in one query
* Don't reuse an Administrator-level token when a scoped role would do
* Don't forget the sandbox suffix on the Realm when connecting to a sandbox account
  {% endcolumn %}
  {% endcolumns %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.coupler.io/sources/category/sales/netsuite/best-practices.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
