Self-hosted: mid-file edit to an upserted document re-embeds nearly all chunks (position-sensitive chunking) — ~21 min CPU per edit on 2 vCPU with local embeddings
Summary
On the self-hosted server, updating an existing document via the /v3/documents customId upsert path re-embeds nearly all of the document's chunks when the edit is anywhere but the tail — a one-paragraph mid-file edit to a 105 KB document re-embedded 1007 of 1102 chunks and pinned a 2-vCPU droplet for ~21 minutes (local embeddings, Xenova/bge-base-en-v1.5).
The chunk-diffing itself clearly exists and works for appends — this looks like position-sensitive chunk boundaries defeating it for mid-file edits.
Environment
- server-v0.0.8 (bun compiled binary;
--versionprints1.3.4), Linux x64, Ubuntu 24.04, 2 vCPU DigitalOcean droplet - Local embeddings (Xenova/bge-base-en-v1.5, CPU)
- Documents are markdown files (50–105 KB) re-posted with a stable
customIdon change (classic "keep reference docs in sync" flow)
Observed
Journal excerpts, same document (customId upsert of a 105 KB markdown file that receives small edits):
12:28:46 Document UYdALezic6sfnHM6DvHqSU embedding 934 chunks (63 batches)
17:06:43 Document UYdALezic6sfnHM6DvHqSU embedding 1007 chunks (68 batches)
17:28:07 Document UYdALezic6sfnHM6DvHqSU stored 1007 embedded chunks
17:28:07 Document UYdALezic6sfnHM6DvHqSU starting memory agent (1102 chunks)
17:28:35 Document UYdALezic6sfnHM6DvHqSU memory agent completed (28084ms, 13 memories)So of 1102 total chunks, 1007 were re-embedded — ~95 reused — for an edit that changed a tiny fraction of the file. Embedding ran 17:06:43 → 17:28:07 (~21.5 min of sustained CPU on this box). Two more reference docs (68 KB → 669 chunks, 51 KB → 550 chunks) do the same on every edit.
Contrast — append-only documents diff perfectly. A chat-transcript document that only ever grows at the tail:
17:28:36 Document E8nykayKLN2z7i4TWE2B6T embedding 5 chunks (1 batches)
17:32:45 Document E8nykayKLN2z7i4TWE2B6T embedding 2 chunks (1 batches)
17:37:59 Document E8nykayKLN2z7i4TWE2B6T embedding 2 chunks (1 batches)Only the new tail chunks embed. So per-chunk reuse exists; it just never gets a hit once an edit shifts every downstream chunk boundary.
Root cause (hypothesis)
Chunking appears to split at fixed positions/sizes from the start of the document. An insertion or deletion early in the file shifts every subsequent boundary, so every downstream chunk's content hash changes and the reuse check misses — O(document) re-embed for O(edit) change. Appends don't shift anything, which is why they diff cleanly.
Suggested fixes
- Content-defined chunking (rolling-hash boundaries, FastCDC-style, or split on stable structural markers like markdown headings): an edit then only invalidates the chunk(s) it touches, boundaries re-synchronize downstream, and the existing per-chunk reuse does the rest.
- Or a cheaper anchor-based resync: after the edited region, try to re-align to the previous chunk sequence by content hash instead of position.
Relationship to other issues
Same self-hosted resource-cost family as #1413 (snapshot re-serialization, since substantially improved in v0.0.7 — thank you) and #1177. For self-hosters running local CPU embeddings, this re-embed behavior is now the dominant CPU cost: any workflow that keeps living documents synced (docs, notes, exports) pays a full re-embed per edit.
Source: supermemoryai/supermemory