Local drafts live in a single JSON array in localStorage; synchronous stringify/setItem grows with total draft size and may eventually hit quota or jank the main thread.
Decision gate: measure first — startup, autosave, near-quota writes, fault injection. Migrate (IndexedDB/native) only if the current design measurably exceeds budget.
Done when: quota/write failures preserve both the stored data and the current edit and surface a clear failure; any migration is versioned, verifiable, resumable, and never deletes old data before the new store reads back successfully.
Local drafts live in a single JSON array in localStorage; synchronous stringify/setItem grows with total draft size and may eventually hit quota or jank the main thread.
Decision gate: measure first — startup, autosave, near-quota writes, fault injection. Migrate (IndexedDB/native) only if the current design measurably exceeds budget.
Done when: quota/write failures preserve both the stored data and the current edit and surface a clear failure; any migration is versioned, verifiable, resumable, and never deletes old data before the new store reads back successfully.