Sync Monitoring

The agent

What the sync agent does on each invocation, and the two ways it is run.

The agent is a single self-contained executable that sits next to a MySQL database. It drains that database's outbox, pushes what it finds to the monitoring server, pulls whatever the other side has queued, and applies it.

Every school runs two of them — one against the on-site database and one against the online database. They are the same binary; only SYNC_SOURCE differs.

SideSYNC_SOURCECapturesAppliesHow it runs
School's on-site databaseLOCALUP tablesDOWN changesResident, --watch
Online databaseONLINEDOWN tablesUP changesOne-shot, under the task scheduler

An agent knows only its own MySQL connection and the server's URL. It never reaches the other database, so the two hosts need no route between them.

One cycle

An invocation is a single cycle. Under --watch the agent repeats it, waiting the school's interval between runs unless it was started with an --interval of its own.

Three details are worth knowing:

Inbound is applied before outbound is captured. Applying first means the rows this cycle pushes already reflect anything that just arrived, so the two sides converge in one pass instead of trading corrections.

A failed apply blocks, it does not skip. The agent stops at the first change it cannot write and refuses to acknowledge past it, so the queue stalls with the error visible rather than quietly leaving a gap. Reading a failure covers what to do with one.

Apply order is respected. Changes leave in the order configured on each table, so a parent is always written before the rows that reference it.

Configuration lives on the server

The agent fetches its configuration at the start of every cycle. Table list, directions, allowed operations and apply order all come from the dashboard, so changing any of them takes effect without redeploying or restarting the agent. The sync interval is stored there too, though only a --watch agent acts on it — see Timing.

The only things held locally are the four connection settings in .env: where the server is, who the school is, its token, and which side this agent is.

Two agents cannot collide

Each cycle takes a MySQL advisory lock named after the database. A run that starts while another is still working logs another run is still in progress and exits, so an overlapping schedule is harmless.

What a healthy run looks like

Run from a terminal, a cycle reports only what it actually moved:

15:30:04  DOWN applied 3, skipped 1 · UP pushed 12                          1.1s

Under a scheduler — where output is redirected to a log — it writes the full form instead, with every number present so the line survives on its own:

2026-08-05T07:36:00.132Z [agent] PAC001 LOCAL — DOWN applied 0, skipped 0, failed 0 | UP scanned 0, pushed 0, dropped 0 across 1 table(s) | counted 0 table(s) | 911ms
NumberMeaning
appliedChanges from the other side written to this database
skippedChanges an operation rule disallowed, or already applied
failedChanges that could not be written — the queue is now blocked
scannedOutbox rows found pending
pushedRows sent to the server after collapsing duplicates
droppedOutbox rows for tables that are no longer configured, or for an operation the table disallows
countedTables whose row counts were refreshed this cycle

The process exits 0 on a clean cycle and 1 when anything failed to apply.

On this page