How to Sync NetSuite Records to MongoDB for Analytics
Mirror NetSuite data in MongoDB for flexible querying and dashboard building.
What This Integration Does
Many analytics and BI tools can't connect to NetSuite directly, or the connection is too slow for interactive dashboards. This workflow runs on a schedule, pulls fresh data from NetSuite via SuiteQL, and writes it into MongoDB collections your dashboards can query freely.
The workflow is re-runnable - each pass upserts records by primary key so re-running won't create duplicates. You can also scope each run to recently-updated records so a single run doesn't have to re-sync the entire dataset.
Prerequisites
- A NetSuite connection with SuiteQL / REST access enabled.
- A MongoDB connection (Atlas or self-hosted) with write access to the target database.
- A target MongoDB database name (e.g.,
netsuite_mirror) and a collection per entity type.
Step 1: Schedule Trigger
Drop a Trigger node onto the canvas and set its type to Schedule. Pick a cadence that matches how fresh your dashboards need to be - daily at 02:00 works well for nightly refreshes, or every 15 minutes for near-real-time. For incremental syncs, the trigger exposes the previous run's timestamp.
Step 2: Variable - Track the Sync Window
Add a Variable assignment to compute this run's window:
syncStart- the previous run's timestamp, or1970-01-01on the first run.syncEnd- the current timestamp.
These two values drive the SuiteQL WHERE clauses in the next step, making each run incremental.
Step 3: Query NetSuite with SuiteQL
Add a Connector node pointing at the netsuite connector and pick the run-suiteql tool. Write a query for each entity you want to mirror, scoped to the sync window. Example for customers updated since the last run:
SELECT id, entityid, companyname, email, datecreated, lastmodifieddate
FROM customer
WHERE lastmodifieddate >= TO_TIMESTAMP('{{ syncStart }}', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
AND lastmodifieddate < TO_TIMESTAMP('{{ syncEnd }}', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
Repeat (or fan out with a Parallel node) for each entity you want to mirror - typically customer, transaction (orders + invoices), item, and vendor.
Step 4: Transform - Shape Records for MongoDB
NetSuite returns flat tabular rows. Use a Transform node to:
- Rename columns from
SCREAMING_CASEtocamelCasefor cleaner Mongo documents. - Set
_idto the NetSuiteid- this is what makes upserts idempotent. - Stamp
syncedAtwith the current timestamp so dashboards can show data freshness.
Step 5: Upsert to MongoDB
Add a Connector node pointing at the mongodb connector and pick the update-documents tool. Configure:
- Database:
netsuite_mirror - Collection: matches the entity (e.g.
customers) - Filter:
{ "_id": "{{ record._id }}" } - Update:
{ "$set": {{ record }} } - Upsert:
true- inserts the document if it doesn't exist yet
Wrap this in a Loop node that iterates over the records from the Transform step.
Step 6: Error Handling and Notifications
Add a Condition node after the upsert to check the result count. On failure (or zero records written), route to a slack send-message call so on-call sees the sync break. Spojit's per-node retry settings handle transient NetSuite or MongoDB errors automatically.
Tips
- Stay under NetSuite's API limits - SuiteQL is far faster than per-record REST calls and won't exhaust your concurrency budget.
- Index for your dashboards -
_idis indexed automatically; also add indexes onsyncedAtand any field your dashboards filter or sort on. - Schema drift - MongoDB is schemaless, but dashboards aren't. When you add a new NetSuite field, run a one-shot full refresh to backfill it.
Common Pitfalls
- Timezones - NetSuite
lastmodifieddateis stored in account timezone. Convert bothsyncStartandsyncEndto that timezone or you'll miss records that fall on the boundary. - Soft deletes - SuiteQL
SELECTs skip inactive records by default. If you also want to mirror deletions, add a separate pass that targetsisinactive = 'T'and marks the Mongo docarchived: true. - Pagination on huge entities -
transactioncan return more than a single SuiteQL page. Loop until the result set is empty rather than relying on a single call.
Testing
Run the workflow once manually with a tiny sync window (the last 5 minutes). Inspect a sample document in MongoDB - field names, types, and _id should look right. Then turn the schedule on.