Skip to content

[Incremental Reprocessing] [MongoDB] stream while snapshotting#641

Merged
rkistner merged 28 commits into
mainfrom
mongo-concurrent-streaming-2
May 21, 2026
Merged

[Incremental Reprocessing] [MongoDB] stream while snapshotting#641
rkistner merged 28 commits into
mainfrom
mongo-concurrent-streaming-2

Conversation

@rkistner
Copy link
Copy Markdown
Contributor

@rkistner rkistner commented May 18, 2026

This is a re-implementation of #450.

This refactors MongoDB replication to:

  1. Split out snapshotting implementation from streaming replication.
  2. Start streaming concurrently with the initial snapshot.

If a table needs a re-snapshot (e.g. due to replica identity changes), this also happens concurrently with streaming (although it still blocks the next commit until it completed). Truncating tables still block the replication stream.

The change

Currently, the replication process is effectively linear / "single threaded". When new sync config is deployed, we create a new replication stream, which performs a snapshot on each table, then starts streaming. This has a couple of limitations:

  1. Replication is slower than it needs to be due to not being able to replicate tables concurrently.
  2. After the initial table snapshots are complete, there could be a significant replication lag that we need to catch up on.

The changes here are also part of the bigger project to implement differential sync config updates - only re-replicating for changed bucket definitions / sync stream definitions. Part of that requires switching to a single replication stream for all copies of sync config, and this builds the base to implement that.

Implementation notes

There is a specific rare but important edge case when we start doing snapshots while streaming: If we don't use soft deletes, as introduced in storage version 3 in #425, then we can miss deletes that were made during the initial snapshot. Due to this, the concurrent snapshots are disabled on the older storage versions. This also adds a test for that specific case. Due to the very specific timing required to reproduce the issue, this adds some storage hooks that allows executing logic before and after a flush. We can investigate using these same or similar hooks to simplify some other tests later, that currently rely on timing only.

The main implementation changes are to move snapshotting to a separate MongoSnapshotter class, using a separate "queue" that can operate concurrently with streaming replication. This does not yet allow using separate processes for snapshot versus streaming yet, or using multiple concurrent snapshotters. Support for those can be added in the future, but requires more careful checks on potential race conditions / consistency issues.

There are additional edge cases around table snapshots: We can now get markSnapshotDone() at the same time that another snapshot is queued. To handle this, the markSnapshotDone() now explicitly checks that there are no pending individual table snapshots. The old markAllSnapshotDone() is still kept around for tests.

The above has a specific effect on MSSQL: There were cases where a capture instance is not present, where the SourceTable was created but the snapshot never performed, which then failed the above check during markSnapshotDone(). This is now changed to not persisted the SourceTable at all in that case.

AI Usage & Implementation notes

Used Codex gpt-5.5 to assist with the implementation, manually guiding and reviewing the changes. At lot of the changes were ported directly from #450, but with additional changes to keep the old behavior for older storage versions, and to fix more edge cases.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 18, 2026

🦋 Changeset detected

Latest commit: 32a5292

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
@powersync/service-module-postgres-storage Minor
@powersync/service-module-mongodb-storage Minor
@powersync/service-module-postgres Minor
@powersync/service-module-mongodb Minor
@powersync/service-core Minor
@powersync/service-module-mssql Minor
@powersync/service-module-mysql Minor
@powersync/service-schema Minor
@powersync/service-image Minor
@powersync/service-module-core Patch
test-client Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rkistner rkistner marked this pull request as ready for review May 19, 2026 11:10
chatgpt-codex-connector[bot]

This comment was marked as outdated.

chatgpt-codex-connector[bot]

This comment was marked as outdated.

@rkistner rkistner marked this pull request as draft May 19, 2026 11:47
@rkistner rkistner marked this pull request as ready for review May 19, 2026 12:20
chatgpt-codex-connector[bot]

This comment was marked as resolved.

@rkistner rkistner marked this pull request as draft May 19, 2026 13:08
@rkistner rkistner changed the title [Incremental Reprocessing] [WIP] [MongoDB] stream while snapshotting [Incremental Reprocessing] [MongoDB] stream while snapshotting May 20, 2026
@rkistner rkistner marked this pull request as ready for review May 20, 2026 09:53
@rkistner
Copy link
Copy Markdown
Contributor Author

@Rentacookie Could you check the CDCStream changes here please? See PR description for background on that.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

@rkistner rkistner force-pushed the mongo-concurrent-streaming-2 branch from fd14b43 to dfdc4a7 Compare May 20, 2026 10:04
@rkistner rkistner requested a review from stevensJourney May 20, 2026 10:57
Comment thread modules/module-mssql/src/replication/CDCStream.ts
Comment thread modules/module-mongodb/src/replication/ChangeStream.ts Outdated
Comment thread modules/module-mongodb/src/replication/ChangeStream.ts Outdated
Rentacookie
Rentacookie previously approved these changes May 20, 2026
Copy link
Copy Markdown
Contributor

@Rentacookie Rentacookie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. I like that most of the snapshotting logic has been split out of the ChangeStream, it makes it much easier to reason about.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dfff28e672

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread modules/module-mssql/src/replication/CDCStream.ts
Copy link
Copy Markdown
Collaborator

@stevensJourney stevensJourney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me also. I really like the addition of hooks to the storage.

@rkistner rkistner merged commit 15e2466 into main May 21, 2026
44 checks passed
@rkistner rkistner deleted the mongo-concurrent-streaming-2 branch May 21, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants