Source health
Shipped
Your Turbobase instance gives you a clear view of whether the sync is running and whether your connected sources are healthy — and the controls to keep a misbehaving source from overwhelming itself.
Service health
Section titled “Service health”Each of your instance’s background services (the sync worker, the realtime listener, and the scheduled-task worker) exposes a health endpoint (/healthz / /readyz) reporting whether it’s up and how long it’s been running. The admin dashboard reads these and surfaces an agents widget marking each service up or down, so a crashed background process is visible rather than silent.
Record types a new release adds switch themselves on. When a release starts syncing a kind of record your connection wasn’t syncing before, your instance adds it to the list your connected system pushes from — by itself, within the hour, on every connection you have. There is nothing to press and nothing to reconnect, and a record type you added to that list yourself is never removed.
The exception is a list you have deliberately taken over: tick Lock Enabled Record Types on the Turbobase configuration record in your connected system and your instance stops changing the list at all. The Enabled record types check on /data/sync/health then names that checkbox rather than asking you to add the types, and its Update button is how you take the new types on when you want them — on a list that isn’t locked, you shouldn’t need it.
Outbound call throttling
Section titled “Outbound call throttling”Every source’s API has a finite concurrency budget. Turbobase puts a per-source call gate in front of outbound requests — a shared queue that caps how many calls to a given source are in flight at once, so your instance never trips a source’s rate limit by fanning out. The cap is configurable per source.
The Data area
Section titled “The Data area”Day-to-day sync monitoring lives in your Turbobase app under /data, a set of tabs that share one spine:
- Overview (/data/sync) — the at-a-glance page: per-source sync throughput, recent call-gate samples showing how busy each source’s gate is, the most recent failures, and a “Mechanic at a glance” summary of what the healing agent is doing (failures awaiting your review, recently fixed, and failures it prevented this week).
- Records (/data/sync/records) — manage which record types sync from each source your instance is mirroring. That is every connected source, plus any source that mirrors on its own schedule without holding a connection — a source with rows in a table its own catalog declares is listed here whether or not it appears under Sources. Rows are grouped by what each record maps to in Turbobase, not by what its source calls it, and the “Maps to” column names that target: the businesses you mirror sit together on the
customerrow whether your system calls them Accounts, Companies, Organizations or Customers, and an accounting chart of accounts keeps a row of its own. Each source’s own name for the record stays on its chip —Zoho CRM · accounton the customer row — so you can still see which record type an app or the write API asks for, and a row’s Rows and Size only count rows that live in that one place. This is also where pending customizations await review and where an in-progress custom-field backfill shows its progress inline on the record’s row. - Activity (/data/sync/history) — the recent sync events (source, direction, record type, state; the source column sorts and filters like the rest) and the history of full sync runs, with a manual “Sync & detect now” trigger for administrators. A source that mirrors on its own schedule writes no sync run, so the Runs view carries a short panel naming those sources, how far each has got, and a link through to the page that owns its detail — for Slack, /settings/slack. The state column says where each event has got to:
pendingmeans it is queued and has not been picked up yet,in_flightmeans your instance is sending it to the connected system right now and is waiting for the system to answer,committedmeans it landed, andfailedmeans it did not and has a row under /data/sync/failures. Some writes take the better part of a minute on the wire — a stock receipt is one — so an event sitting onin_flightis a write in progress rather than a queue that has stopped. - Late arrivals (/data/sync/late-arrivals) — the records the scheduled catch-up delivered first, so the realtime push missed them. See below.
- Health (/data/sync/health) — a per-source set of health checks, each reporting pass, warn, or fail, rolled up into an overall status.
- Sources (/data/sources) — your connected sources, with per-source pages for credential status, secret rotation, a connection test, and reconnect. Connecting a new source happens through the “+ Add a connection” picker, which hands off to the console’s connect flow.
When data sync is off
Section titled “When data sync is off”An instance can be connected to a source and deliberately not mirror its records — the customizations-only posture chosen in the connect wizard’s Advanced settings (see Connect your first source). Customization discovery, schema reconcile and the Analyzer all run; record data does not land.
/data/sync says so at the top rather than showing an empty dashboard: the throughput and failure figures below read as nothing by design, and this is not treated as an outage — it raises no alert. When only some of your sources are in that posture, the banner names them.
To start mirroring, open the source’s page under /data/sources and use Enable data sync. The historical backfill starts on its own and runs in the background; the record tables already exist and are empty, so the backfill lands in columns that already match. Enabling asks you to confirm, because once enabled it can’t be disabled.
When a connection is paused
Section titled “When a connection is paused”A paused connection is not a failing one, and your instance says so rather than leaving you to work it out from a flat graph.
Pausing is done from the console (see Add sources) and acts on one connection: if you hold two NetSuite accounts you can pause one and leave the other syncing.
A pause stops the traffic in both directions:
- No new records are brought in. The connection drops out of the scheduled sync’s targets and its incoming webhooks are accepted and discarded.
- Nothing you change here is sent back to it. An edit or a delete you make against a record mirrored from a paused connection is refused where you make it, with a message saying the connection is paused — never accepted and then quietly not sent, which would leave you believing the change had landed in your account.
Everything already mirrored is untouched, so your apps, queries and reports carry on reading it.
Where you see it:
- /data/sources marks the connection Paused on its row, with a link through to the console page that resumes it. A source holding two connections badges only the paused one.
- Health (/data/sync/health) reports it as a pass with a note, not a warning. A paused connection has an idle sync chain by design, and a health surface that is permanently amber is one nobody reads.
- The sync run’s own output names it —
this connection is paused — resume it to sync it again— so a quiet run says why it was quiet.
Resuming clears the pause and the connection is back in the next run’s targets. It picks up from wherever the source is then; nothing is replayed from the paused window beyond what the source’s own change feed still carries.
This is a different switch from data sync above: that one is per source, chosen once, and only goes on. Pause is per connection and always reversible.
When a source refuses a connection
Section titled “When a source refuses a connection”A pause is your decision. A refusal is the source’s, and it usually arrives without anyone deciding anything: someone revokes the app’s access, or the connected user’s role changes, and the source starts turning down one kind of record.
Your instance notices after a few refusals and stops sending changes of that kind on that connection. It keeps going for everything else — a grant that lost one kind of record kept the rest, and a connection that lost nothing is untouched. If you hold two accounts of the same source, only the refused one is held back.
Nothing is lost while a connection is refused. Every record you create or change is accepted here and held, exactly as it is when a write fails for any other reason. What stops is the pointless part: your instance no longer asks the source a question it has already answered, so your source’s rate limit isn’t being spent on calls that cannot succeed.
Where you see it:
- Health (/data/sync/health) carries one row naming the source and the kinds of record it is refusing, with reconnection as the fix. One row for the problem, not one per record held.
- /data/sync/failures lists the held records themselves, as it does for every other kind of write failure.
To clear it, reconnect the source from its page under /data/sources. If the refusal is a permission rather than an expired sign-in, widen the connected user’s access in the source first, then reconnect. The held records go through by themselves afterwards — there is nothing to re-queue and nothing to retry by hand.
It also clears itself. Every so often your instance lets one change through to see whether the source will take it. If it does, the connection resumes immediately and the records waiting on it go through the same way; if not, it stays held and tries again later. So a grant somebody fixes without telling you starts working again on its own.
Late arrivals
Section titled “Late arrivals”Changes reach your instance two ways: a realtime push the moment a record is saved in the source, and a scheduled catch-up that sweeps for anything the push missed. The push is what makes your data feel live; the catch-up is a safety net.
A late arrival is a change the catch-up delivered first — so no realtime push arrived for it. Something in the source system changed that record without telling your instance at the time: a script, a batch job, an import with server scripts switched off, or another integration writing through a path the realtime trigger does not cover. /data/sync/late-arrivals lists them, so you can see where the gap is and fix it at the source.
What counts, and what does not. A change counts as a late arrival only if the catch-up actually applied it. When the catch-up re-reads a record the realtime push had already delivered, it finds nothing changed and nothing is recorded — a re-read that matched is not a late arrival. The same holds for a deletion already recorded, and for a record your instance does not mirror.
Nor does the first copy of your data. When you connect a source, your instance mirrors what that source already holds. None of it is a late arrival: those records were not changed while your instance was watching, so there was no realtime push to miss. The tab counts from the moment that first mirror finishes.
That holds per record type, not just per connection. A record type can get its first copy long after you connected — you approve a custom record or a custom module, or a Turbobase release starts mirroring something new. The first pull of its existing rows is a copy of what was already there, so none of it is counted, whichever source it comes from. Changes to that record type from then on are counted as they are for everything else.
And it holds however long that copy takes. A record type with a lot of history can need several sweeps to copy — each sweep works for a bounded window and the next one carries on where it stopped. Your instance records when a record type’s copy starts and when it finishes, so every sweep in between is part of the copy and none of it appears here. A record type that stops part-way, or whose source is briefly unreachable, is continued rather than counted.
Two cadences, so “late” means different things. Creates and edits catch up on the four-hourly sweep, deletions on an hourly one. A record edited by a script can therefore sit up to four hours behind, while a record deleted the same way is at most an hour behind.
The tab groups by connection, record type, and whether the change was a create, an edit or a deletion — because the fix differs for each, and a gap on one of two connected accounts is a different gap from one on both. Beside each count is that record type’s realtime rate: how many of its changes arrived in realtime rather than through the catch-up. A count alone is unreadable — forty late arrivals is excellent on a connection handling forty thousand changes and alarming on one handling forty. Open a row to see the individual records with the source’s own modified time, when your instance caught up, and the delay between the two. Times are shown in UTC.
Click a record to see what actually changed. A panel opens beside the list with one line per field that moved, the value before and the value after, and everything that stayed the same behind a disclosure. It is read from the audit trail at the moment you click — the list itself never reads it, so the tab stays as quick as it is.
That answers a question the count on its own cannot. “Customer updated” can mean a real edit at the source, or movement in fields your instance does not mirror at all — and those are not the same finding. When nothing your instance records moved, the panel says so in words rather than showing an empty list, and tells you why: the edit was in source fields that are not mirrored, or in the raw payload that is not kept. A create shows the values it started with and no “before” side; a deletion shows the last values recorded and no “after”. A source-reported deletion marks the record as deleted rather than removing it, and that marking is not itself a change your instance records — so what you see is the last thing the source wrote to the record before it went. On a record your instance no longer holds at all, the panel says there are no last values to show, rather than offering an earlier change as the deletion’s. If the trail cannot be read, the panel says that too — never that nothing changed.
The fix is at the source, not here. Shortening the catch-up interval would narrow the delay without closing the gap. What closes it is at the source — but which thing differs from one connection to the next, so your instance works that out rather than assuming it.
Press “How to fix” for which gap it actually is. The button appears beside the filters whenever something is late on a source that can push, and opens a panel on the page — one section per affected connection, saying which of two different faults that connection has. Either realtime delivery is not arriving at all, because it was never set up for that account or the deliveries are being turned away, which is fixed by connecting the source; or the deliveries are arriving and something keeps saving certain records without announcing it, which is fixed in the script doing the saving. A 0% realtime rate is equally consistent with both, so your instance checks its own delivery record rather than guessing — and when it cannot read that record, the section says the delivery state could not be checked rather than naming a fault nothing confirmed.
For NetSuite the second section names the record types still arriving on the catch-up and shows the two-line notify call that closes the gap, and both link to Real-time sync from your own NetSuite scripts, which covers the four cases NetSuite does not report. A poll-only connection is named as arriving on the schedule by design, with nothing to fix.
Unless the source has no realtime path at all. Some systems offer no way to tell your instance about a change as it happens — nothing to subscribe to, or nothing that identifies the notification as genuinely theirs. For those, the scheduled catch-up is how their data arrives, by design. Such a connection is marked Poll-only on the tab, with no realtime rate against it: there is no trigger at the source to fire and nothing for you to fix. Its changes are still listed, because you may well want to see them; they are simply not a missed delivery. The two figures at the top of the tab say how much of the count came from those connections and how many of them the realtime rate leaves out, so neither number reads as a fault that is not there.
An empty tab is good news: every change in the window arrived in realtime. The list counts from when this feature reached your instance forward — there is no history before that.
Administrators only, like the rest of the Data area.
Sync failures
Section titled “Sync failures”When a record can’t be written back to its source, it doesn’t disappear and it doesn’t retry forever. The failure is recorded as a single deduplicated row — repeated failures of the same record collapse into one row with an occurrence count, rather than flooding you with near-identical entries. Administrators triage these at /data/sync/failures, where each failure can be approved, rejected, ignored, muted, retried, or edited-and-retried. Every such decision is written to the audit log.
This pairs with the guardrails that stop a terminal write failure from re-enqueuing itself in a tight loop.
Related
Section titled “Related”- Data model — bidirectional writes and where failures come from
- Guardrails — the sync-loop circuit breakers