Sync Architecture
Nodes Online
—
A2 Hosting · LocalDB
Active Failovers
—
A2 Hosting · LocalDB
Active Sync Triggers
—
5 triggers · Master Workflow v3.4 · 80 nodes
Sync Flow — Failover Chain
A2
A2 Host
LO
Local
n8
n8n
—
Nodes Online
—
Active Failovers
—
WF Active
—
sync_log
Sync Health Score
Live
History
Node Uptime
Last Synced
— waiting for first sync —
⚡
LIVE DATA SYNC MONITOR
via n8n Cloud · auto-check every 5 min
● No Webhook
→
A2 Hosting
Mirror · cPanel
Waiting
→
Local MySQL
Backup
Waiting
via
n8n Cloud
7 sync + live parity · 80 nodes
Waiting
Last run: —
Duration: —
Result: —
Records synced: —
Sync Event Log
No sync events yet — run a sync to begin.
n8n Cloud
Orchestrator
1 master workflow · 5 triggers
Unknown
Health & Recovery: every 5 min
Record Parity
Unknown
A2 vs Local · approx (information_schema)
Waiting for first check…
A2 Hosting
—
Local
—
Difference
—
Tables matched
—
Workflow Schedules
Full Sync WF1 · 6 nodes · A2→Local (nightly reload)
—
Incremental Sync WF2+WF3 · 14 nodes · A2↔Local (bidirectional)
—
Failover & Recovery WF4+WF5 · 13 nodes · Detection+Push
—
Dashboard scheduler: pick a time/interval from the dropdown, then turn ON the master Auto-trigger. At the chosen time, the dashboard itself fires the workflow (same as the Full Sync / Incremental / Failover buttons above).
Each row has its own toggle: while the master Auto-trigger is ON, only the rows whose adjacent switch is ON are included in auto-firing — turn a row OFF (e.g. Full Sync) to keep it manual/nightly only. (Manual clicks above always work, regardless of any toggle.)
Failover Chain
Normal → A2 ↔ Local bidirectional sync (15 min)
Failover → operator manually promotes the surviving node
Recovery → last-writer-wins UPSERTs reconcile on next sync
Conflict policy → row with newer updated_at wins
Master Workflow v3.4 — Node Explorer
7 sync workflows + live-parity viewer combined into 1 · 5 triggers · 6 webhooks · 80 nodes total
⚡ WF6 Live Webhook — Connect Dashboard
● Not Connected
Paste your WF6 webhook URL from n8n. Once connected, all sync data is pulled directly from your actual
sync_log table.Last fetch: —
WF6 Setup Steps — Import to n8n
1
Import the updated JSON
Download
mysql_db_sync_master_workflow_v3_4.json and import it into n8n. WF6 Webhook node is already included.2
Set WF6_WEBHOOK_URL variable
In n8n: go to Settings → Variables → add
WF6_WEBHOOK_URL = your WF6 webhook URL. All workflows use this variable to notify the dashboard after every run.3
Activate WF6 in n8n
Activate the WF6 workflow in n8n. Your production webhook URL will appear on the WF6 node — format:
http://localhost:5678/webhook/db-sync-status4
Paste the URL above and click Connect
Copy the production URL into the input above, then press Connect. All tabs (Dashboard, Nodes) will update using your actual
sync_log data. WF6 Response Payload — Reference
This is the JSON that WF6 returns to the dashboard — straight from the
sync_log table:{
"nodes_online": 2, // 0–2, based on failover flags
"active_failovers": 0, // count of nodes in failover
"failover_a2": false, // true if A2 is down
"failover_local": false, // true if LocalDB is down
"wf_active": 3, // workflows with status=success
"records_synced": 5, // sync_log success row count
"triggers": {
"full_sync": "success", // WF1 (A2→Local nightly) last status
"a2_to_local": "success", // WF2 last status
"local_to_a2": "success", // WF3 last status (NEW direction)
"health_check":"ok" // WF4 current state
},
"last_synced": {
"full_sync": "2026-05-21T02:00:05Z",
"a2_to_local": "2026-05-21T14:15:03Z",
"local_to_a2": "2026-05-21T14:15:04Z"
},
"generated_at": "2025-05-21T14:32:00Z"
}
Setup Scripts (Run These First)
Run these 2 scripts on BOTH databases (A2 Hosting and LocalDB) before activating the n8n workflow.
1. Create sync_log Table
Required by WF1–WF6. Tracks sync state per table + workflow.
2. Add updated_at Columns
100 tables need updated_at for full incremental sync (52 missing it, 48 lack any timestamp).
3. n8n Workflow v3.4
Master workflow JSON — 80 nodes (7 sync workflows + live-parity viewer · 6 webhooks), all 126 tables embedded. Activate to register the webhooks.
Import in n8n: Workflows → ⋯ → Import
Quick SQL — Monitoring Queries
Sync Health Check (Local MySQL)
SELECT workflow_name, table_name, last_synced_at, status, notes
FROM sync_log
ORDER BY last_synced_at DESC;
Record Count Comparison (TGC_ERP)
-- Runs on whichever DB is connected (A2 or Local) — no hardcoded name.
SELECT table_name, table_rows AS est_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_type = 'BASE TABLE'
ORDER BY table_rows DESC;
Records Updated in Last Hour (per table)
-- Pick a table from the schema browser below
SELECT COUNT(*) AS new_records
FROM `orders` -- change to any table that has updated_at
WHERE updated_at >= NOW() - INTERVAL 1 HOUR;
Per-Table Sync Lag
-- Valid workflow_name values (v3.1): full_sync, a2_to_local, local_to_a2,
-- health_check, reconciliation, repair
SELECT table_name,
MAX(last_synced_at) AS last_sync,
TIMESTAMPDIFF(MINUTE, MAX(last_synced_at), NOW()) AS lag_minutes
FROM sync_log
WHERE workflow_name = 'a2_to_local' -- WF2 incremental A2->Local
GROUP BY table_name
ORDER BY lag_minutes DESC;
Tables Missing updated_at Column
SELECT t.table_name
FROM information_schema.tables t
LEFT JOIN information_schema.columns c
ON t.table_schema = c.table_schema
AND t.table_name = c.table_name
AND c.column_name = 'updated_at'
WHERE t.table_schema = DATABASE()
AND t.table_type = 'BASE TABLE'
AND c.column_name IS NULL
ORDER BY t.table_name;
TGC_ERP Schema Browser
126 tables · 517,040 rows · all 3 databases identical (schema + data)
Before Importing to n8n workflow v3.4 · 80 nodes
Workflow v3.4 — everything is merged in (7 sync workflows + live-parity viewer · 6 webhooks, 126 tables embedded). Here's all that's left to do:
✓
Auto: Table Names
Every
your_table_name is already replaced with a dynamic reference ($workflow.staticData.global.CURRENT_TABLE)
✓
Auto: Column Names
UPSERT queries already use dynamic columns from the embedded schema map (126 tables)
⚠
Run sync_log setup script
Go to SQL Tools → download
sync_log_table.sql → run on all 3 databases
⚠
Run ALTER TABLE migration (recommended)
100 tables are missing
updated_at. Without it, updates won't sync. Get script from SQL Tools.
⚠
Create 2 MySQL credentials in n8n
Names must be exact (match the JSON):
MySQL_Cloud (A2 Hosting), MySQL_Local (LocalDB)
✓
Auto: Table Queue (no manual CURRENT_TABLE)
In v3.1,
WF1/WF2/WF3/WF5: Init Queue builds the whole table list — you no longer need to manually set CURRENT_TABLE in staticData.
⚠
Activate the workflow
Toggle Active (top-right) — if it isn't active, the 6 production webhooks (
db-sync-status, db-repair, db-full-sync, db-incremental, db-failover, db-live-parity) won't register and the force-run buttons return 404.
⚠
Replace Alert Webhook URL
Set the real endpoint in
WF4: Send Alert (default: placeholder). There is no separate recovery-notification node in v3.1.Common Issues & Fixes
Can't connect to Local MySQL
Check Fortinet policy · verify n8n egress IPs whitelisted · port 3306 open to 10.10.20.11
Can't connect to A2 Hosting
cPanel → Remote MySQL Access → ensure % wildcard added
Incremental sync missing changes
Verify updated_at has ON UPDATE CURRENT_TIMESTAMP on BOTH databases
Failover flag stuck on 'failover'
Run WF5 manually, or:
UPDATE sync_log SET status='success'Full sync timeout
Use SplitInBatches node · increase n8n timeout setting