← All posts Uncategorized 4 min read

NetSuite SuiteQL for WooCommerce Integrations: Replacing Saved Searches at Scale

Learn why NetSuite SuiteQL outperforms saved searches for WooCommerce integrations at scale — with practical query patterns for inventory, orders, and pricing sync.

SuiteQL is NetSuite’s SQL-like query language for the Analytics Data Source. For WooCommerce integrations built on the legacy REST API with saved searches as the data-retrieval layer, SuiteQL isn’t optional anymore — it’s the path to queries that actually perform at production volume. Saved searches work fine at low order counts. They stop working reliably once your catalog hits tens of thousands of SKUs or your order volume crosses into the hundreds per hour.

Why Saved Searches Break Under Integration Load

Saved searches were designed for human-facing reporting inside NetSuite’s UI. They process results server-side, apply formula columns at runtime, and return paginated results that integrations poll sequentially. At low volume this is invisible. At scale the problems compound:

  • Governance points are charged per request, and saved search polling burns them quickly under high-frequency sync schedules
  • Saved search results can’t be indexed the way a database query plan can be optimized — you have no control over execution strategy
  • Join behavior across record types is opaque; you can’t predict performance when the dataset grows
  • Formula columns (inline SuiteScript) execute on every row, every time

SuiteQL solves these by giving you direct access to NetSuite’s underlying record tables with a standard SQL syntax. You control exactly what columns you pull, how joins are structured, and how results are filtered and ordered.

The Core SuiteQL Endpoint for WooCommerce Integrations

SuiteQL queries run against the suiteql endpoint in the NetSuite REST API:

POST /services/rest/query/v1/suiteql
{
  "q": "SELECT id, itemid, salesdescription, baseprice FROM item WHERE isinactive = 'F' ORDER BY id"
}

Results return as JSON with a hasMore flag and offset parameter for pagination. The integration pulls pages sequentially until hasMore is false. This is structurally identical to saved search pagination but with dramatically better query control.

Practical SuiteQL Patterns for WooCommerce Sync

Three queries cover the majority of WooCommerce integration data needs:

Inventory by location:

SELECT il.item, il.location, il.quantityonhand, il.quantityavailable
FROM inventorybalance il
WHERE il.location IN (1, 2, 3)
AND il.quantityavailable > 0

Orders since a timestamp (for incremental sync):

SELECT t.id, t.trandate, t.entity, t.status, t.foreigntotal
FROM transaction t
WHERE t.recordtype = 'salesorder'
AND t.lastmodifieddate > TO_TIMESTAMP('2026-06-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY t.lastmodifieddate ASC

Item pricing by price level:

SELECT ip.item, ip.pricelevel, ip.unitprice, ip.currency
FROM pricing ip
WHERE ip.pricelevel IN (1, 5)
AND ip.currency = 1

Incremental Sync vs Full Refresh

The most important SuiteQL pattern for integrations is incremental sync using lastmodifieddate. Every NetSuite record type exposes this field. A sync loop that stores the timestamp of its last successful run and queries WHERE lastmodifieddate > :last_run processes only changed records instead of the full dataset. For a catalog of 50,000 items with 200 daily changes, incremental sync cuts per-cycle query load by roughly 99%.

Store the last-run timestamp in your integration’s state layer (Redis, a database row, or a simple file), update it only after a successful sync cycle completes, and never advance it on partial failures. Advancing the cursor on failure causes the next run to miss the records that failed to process.

Governance and Rate Limits

SuiteQL queries consume concurrency slots, not governance points. NetSuite allows a fixed number of concurrent SuiteQL requests per account (the limit varies by license tier). For integrations running multiple sync workers in parallel, implement a semaphore that caps concurrent SuiteQL calls at a safe limit — typically 3–5 — to avoid HTTP 429 responses from the analytics endpoint. SuiteQL 429s are retriable with exponential backoff; treat them as transient and build retry logic into the query layer.

Migration Path from Saved Searches

The pragmatic migration approach is to run SuiteQL and saved search results in parallel for one week, comparing output to validate parity before cutting over. Pay particular attention to inactive records: SuiteQL queries against the analytics data source include inactive records unless you explicitly filter them out, while some saved searches exclude them by default. Mismatches in this area are the most common source of post-migration sync errors.


Ship it

Need this in your stack?

We build, integrate, and ship — no calls, just delivery.

Start a project →