Is a theoretically RELIABLE incremental backup even possible with the Notion API? (Spoiler: Probably not)
Hi everyone,
I’m currently building NotionManager, a local-first desktop app designed to snapshot Notion workspaces into a block-based local DB for high-fidelity offline viewing.
While full snapshotting works beautifully, I’ve spent weeks trying to implement an incremental backup feature to save users from re-downloading gigabytes of data. After digging deep into the implementation, I’ve hit a wall that isn’t just about rate limits—it’s about fundamental API design flaws.
Here is the engineering reality. I’ve come to the conclusion that a truly reliable incremental backup tool cannot be built on top of the current Notion API. Change my mind.
Here is the breakdown of why it breaks down:
1. The LACK of a Traversal Endpoint
Notion provides no native way to traverse or stream the workspace graph from the root. You cannot ask for a changelog or a delta stream.
2. The Broken last_edited_time Behavior
Every object has a last_edited_time, which sounds promising, but its behavior makes it useless for mutation detection:
- Minute-level Resolution: The timestamp resolution is capped at the minute level. For rapid programmatic changes or busy workspaces, this granularity is blind to rapid successive mutations.
- No Topology Bubble-up: Updating a child block or a sub-page does not bubble up and update the
last_edited_timeof the parent page. The parent remains frozen in time. Worse, this behavior is completely undocumented and requires constant trial-and-error to map out.
3. The Entrance Problem (No Global Catalog)
Objects do maintain parent topology information, which is great, but you still need a global entry point to start recursing down.
4. The Hack: Forcing /v1/search into a Global Router
The only global entry point available is the /v1/search endpoint. It guarantees that any object explicitly shared with the integration will show up. This works as a baseline for full backups, allowing us to maintain a global flat list of entry points (pages and databases).
5. Why Incremental Discovery is an Illusion
For incremental backups, you must discover newly created objects. Currently, there is no reliable mechanism for this. With precise tuning, /v1/search seems to surfaced new objects eventually. But here is the catch: it offers zero API contract guarantees. Search indexes can be delayed, rate-limited, or completely omit items without violating the endpoint’s design contract (since it’s meant for humans searching keywords, not machines syncing state).
The Bitter Conclusion
If we blindly trust that the /v1/search index behavior remains consistent, we can hypothetically discover new objects, combine them with our previous global list, and check individual last_edited_time stamps to build a "near-usable" sync.
Unfortunately, "near-usable" is completely unacceptable for a backup solution.
Because the search API offers no contractual guarantees, the sync engine could quietly miss a newly created sub-page, fail silently, and cause catastrophic data loss without the user or the app ever knowing.
Therefore, my architectural conclusion is absolute: Under the current API design, a reliable incremental backup for Notion is impossible. You either pull the entire world every time via full snapshots, or you accept silent corruption.
To anyone who has wrestled with Notion's data model or built sync engines on top of legacy web APIs: Am I missing a hidden workaround, or have you all forced your users into mandatory full snapshots as well?
Would love to hear your thoughts or architectural post-mortems on this!