How to Reconcile MongoDB and MySQL Records Daily with AI Diff Summaries
Build a Spojit workflow that runs every morning, compares the same records held in MongoDB and MySQL, computes a field-by-field diff, and has Miraxa turn the differences into a plain-language summary posted to Slack.
What This Integration Does
When the same data lives in two systems, a document store in MongoDB and a relational table in MySQL, the two copies drift apart over time: a price gets edited in one place, a status update fails to propagate, a row is deleted on one side but not the other. This workflow gives you a daily, hands-off reconciliation: it pulls the records from both databases, lines them up by a shared key, and flags every field that no longer matches. Instead of reading raw diff output, your team gets a short, readable summary in a Slack channel that says what changed, where, and how many records are affected.
The workflow is started by a Schedule trigger on a daily cron, so no one has to remember to run it. On each run it reads from MongoDB and MySQL, uses the json connector to compute differences, and then an agent-mode Connector step asks Miraxa to describe the discrepancies in business terms before a Slack step posts the result. Each run is independent and stateless: it reads the current state of both databases, reports on it, and writes nothing back. Re-running it (manually or on the next schedule) simply produces a fresh report against whatever the data looks like at that moment, so it is safe to run as often as you like.
Prerequisites
- A MongoDB connection added in Spojit (Connections -> Add connection), pointing at the database that holds one copy of the records.
- A MySQL connection added in Spojit, pointing at the database that holds the other copy.
- A Slack connection (OAuth) with permission to post to the channel where you want the summary, plus the target channel name or ID.
- A shared key that identifies the same record in both stores (for example an
order_idorsku) so rows and documents can be matched up. - The json connector, which is built in and needs no authentication.
Step 1: Schedule the daily run
Add a Trigger node and set its type to Schedule. Enter a 5-field Unix cron expression and an IANA timezone so the comparison runs at a predictable local time. For 7am on weekdays in Sydney, use 0 7 * * 1-5 with timezone Australia/Sydney. A single Schedule trigger can hold more than one schedule if you want it to run multiple times a day. The trigger output is simply {{ scheduledAt }}, which you can include later for context. No request body is needed because the workflow reads everything it needs from the two databases.
Step 2: Read the records from MongoDB
Add a Connector node in Direct mode, choose the MongoDB connector, and select the find-documents tool. Set collection to the collection you are reconciling, and supply a filter that scopes the run to a manageable, comparable slice of data (for example records updated recently, or a single status). Use sort on your shared key and an explicit limit so both sides return the same population in the same order. A typical configuration:
collection: orders
filter: { "status": "open" }
sort: { "order_id": 1 }
limit: 500
The tool returns its results under data.documents with a data.count. Name this step's output something like mongo so you can reference {{ mongo.data.documents }} downstream.
Step 3: Read the matching rows from MySQL
Add a second Connector node in Direct mode, choose the MySQL connector, and select the execute-query tool. Write a SELECT that returns the same fields and the same scope as the MongoDB query, ordered by the shared key so the two result sets align. Use ? placeholders and the params array for any values rather than concatenating them into the SQL string:
query: SELECT order_id, status, total, updated_at
FROM orders
WHERE status = ?
ORDER BY order_id ASC
LIMIT 500
params: ["open"]
Name this step's output mysql. Keep the selected columns and their names consistent with the document fields from MongoDB so a like-for-like comparison is possible in the next step.
Step 4: Compute the diff with the json connector
Add a Connector node in Direct mode, choose the json connector, and select the diff tool. Map the two result sets into its inputs: set obj1 to the MongoDB documents and obj2 to the MySQL rows. Because diff compares leaf values by path, the cleanest approach is to feed it the two ordered collections so equivalent records sit at the same index:
obj1: {{ mongo.data.documents }}
obj2: {{ mysql.rows }}
If the two systems expose rows in a different shape, add a Transform node before this step to reshape each side into a comparable structure (for example keying each record by its order_id) so the diff lines up records rather than positions. The diff tool returns differences (a list of { path, type, oldValue, newValue } entries where type is added, removed, or changed) and a count. Name this output diff. When count is 0, the two copies are identical.
Step 5: Summarize the discrepancies with Miraxa
Add a Connector node in Agent mode. Agent mode lets Miraxa, the intelligent layer across your automation, reason over the raw diff and explain it in business terms rather than leaving you to read path-and-value pairs. Pass the diff into the prompt and ask for a concise summary:
You are reconciling order records between MongoDB and MySQL.
Here are the field-level differences found today
({{ diff.count }} total):
{{ diff.differences }}
Write a short summary for a Slack channel. Group the
differences by record where possible, call out which
system holds which value (obj1 is MongoDB, obj2 is MySQL),
and highlight anything that looks like a missing or
deleted record. Keep it under 200 words.
To make the output easy to post and reuse, open the Response Schema and force structured JSON, for example a headline string and a details string. Name this step summary. Agent mode consumes AI credits, so keep the prompt focused on the diff you already computed rather than asking it to re-fetch data.
Step 6: Post the summary to Slack
Add a final Connector node in Direct mode, choose the Slack connector, and select the send-message tool. Set the channel to your reconciliation channel and build the message text from the schedule context and Miraxa's summary:
channel: #data-reconciliation
text: Daily MongoDB vs MySQL reconciliation ({{ scheduledAt }})
{{ summary.headline }}
{{ summary.details }}
Differences found: {{ diff.count }}
If you would rather a clean "all clear" message on days with no drift, add a Condition node after Step 4 that checks whether {{ diff.count }} is greater than 0: route the true branch through Steps 5 and 6, and the false branch to a short send-message that confirms the two databases matched.
Tips
- Keep both queries scoped to the same comparable slice (same filter, same ordering, same
limit) so the diff reflects real drift and not just different row counts. - Sort both sides by the shared key. Index-based comparison only works when equivalent records line up; a Transform node that keys each record by its ID before the
diffstep makes the result far more reliable. - Use the
countfrom thedifftool to gate the AI step. There is no reason to spend AI credits summarizing zero differences. - If you want a daily archive instead of just a Slack ping, you can add a MongoDB
insert-documentsor MySQLinsert-rowsstep to record the diff result for trend tracking.
Common Pitfalls
- Type mismatches read as differences. A number stored as
100in MySQL and"100"in MongoDB will show up as achangedentry. Normalize types in a Transform step before diffing. - Unbounded result sets. Without a
limit, a large collection or table can return far more than you intend to compare. Always cap both queries and reconcile in scoped batches. - Timezone drift. The Schedule trigger runs in the IANA timezone you set, not the server's. Confirm the timezone so the daily run lands when you expect, especially around daylight-saving changes.
- Volatile fields. Columns like
updated_ator last-synced timestamps almost always differ and will flood the diff. Exclude them from the MySQLSELECTand the MongoDBprojectionunless you specifically want to track them.
Testing
Before turning the schedule on, validate the logic on a small scope. Temporarily tighten both queries to a handful of known records (for example a single order_id via the filter and a matching WHERE clause), then use the Run button to execute the workflow on demand. Open the execution log and inspect each step: confirm the MongoDB and MySQL outputs return the same records, check that the diff step's count matches what you expect (deliberately edit one value in one database to force a known difference), and verify the Slack message reads clearly. Once a small run looks right, widen the queries back to your real scope and let the Schedule trigger take over.
Learn More
- MongoDB connector reference
- MySQL connector reference
- json utility connector reference
- Schedule trigger and other trigger types
- How to Build a MySQL to MongoDB Data Pipeline
- How to Use SQL Queries to Drive Workflow Decisions
- Using Connector Nodes in Direct Mode
- Using Connector Nodes in Agent Mode
- Setting Up a Schedule Trigger