[Windows] Composer autosave triggers repeated full rewrites of .codex-global-state.json and .bak, causing severe SSD write amplification
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
Codex Desktop for Windows: OpenAI.Codex_26.901.6511.0_x64__2p2nqsd0c76g0
What subscription do you have?
Typing or editing text in the Codex composer causes repeated full rewrites of the entire .codex-global-state.json and .codex-global-state.json.bak files. The actual composer draft mutation is very small (usually tens or hundreds of bytes), but each autosave triggers an atomic rewrite of approximately 1.25 MB for the primary global-state file and another approximately 1.25 MB for the backup. This causes significant SSD write amplification during normal composer editing. The issue is specifically correlated with electron-persisted-atom-state -> composer-prompt-drafts-v2. When the composer is idle, the writes stop. When Codex is running/inferencing but the composer is not being edited, the draft watcher also remains idle.
What platform is your computer?
Windows 11 x64
What issue are you seeing?
What version of the Codex App are you using?
Codex Desktop for Windows:
OpenAI.Codex_26.901.6511.0_x64__2p2nqsd0c76g0
The Electron frontend process is:
ChatGPT.exe
The app-server process is:
codex.exe
What platform is your computer?
Windows 11 x64.
What issue are you seeing?
Typing or editing text in the Codex composer causes repeated full rewrites of the entire .codex-global-state.json and .codex-global-state.json.bak files.
The actual composer draft mutation is very small (usually tens or hundreds of bytes), but each autosave triggers an atomic rewrite of approximately 1.25 MB for the primary global-state file and another approximately 1.25 MB for the backup.
This causes significant SSD write amplification during normal composer editing.
The issue is specifically correlated with electron-persisted-atom-state -> composer-prompt-drafts-v2.
When the composer is idle, the writes stop.
When Codex is running/inferencing but the composer is not being edited, the draft watcher also remains idle.
Reproduction
-
Start Codex Desktop on Windows.
-
Open an existing thread or a new thread.
-
Monitor:
C:\Users\<user>\.codex\.codex-global-state.json*with Sysinternals Process Monitor.
-
Leave the composer idle for several minutes.
Result:
- no repeated global-state writes
- no
composer-prompt-drafts-v2mutations
-
Start typing normally in the composer.
-
Observe repeated mutations to:
electron-persisted-atom-state -> composer-prompt-drafts-v2 -
At the same timestamps, ProcMon shows repeated full writes to temporary files such as:
..codex-global-state.json.tmp-<uuid>and
..codex-global-state.json.bak.tmp-<uuid> -
Each temporary file is then atomically renamed/replaced into:
.codex-global-state.jsonor
.codex-global-state.json.bak -
Stop typing.
Result:
- the draft mutations stop
- the repeated global-state rewrites stop
ProcMon evidence
Each global-state serialization is approximately:
- WriteFile: 524,288 bytes
- WriteFile: 524,288 bytes
- WriteFile: ~207,000 bytes
Total per temporary file:
~1,256,000 bytes
The same state is written separately to:
.codex-global-state.json.codex-global-state.json.bak
So one logical autosave can result in approximately:
~2.5 MB of file writes
even though the underlying draft mutation may only be a few bytes.
Draft mutation evidence
During normal typing, the composer-prompt-drafts-v2 state changes every ~1–few seconds.
Example:
- 11 -> 84 bytes
- 84 -> 81 bytes
- 81 -> 82 bytes
- 82 -> 84 bytes
- 84 -> 88 bytes
- 88 -> 150 bytes
The same draft content is also mirrored under two keys:
client-new-thread:<id>local:<thread-id>
Both entries change in sync.
The important point is that a very small composer-state mutation causes a full ~1.25 MB global-state rewrite plus another ~1.25 MB backup rewrite.
A/B test: typing vs paste
Typing a short prompt manually produced approximately:
25,131,020 bytes
of writes to the global-state temporary files.
Pasting a much larger prompt in one operation and sending it produced approximately:
13,829,857 bytes
of writes.
The paste test caused only a few draft-state transitions:
- clear old draft
- set pasted draft
- clear after submit
This strongly suggests that write volume is driven by composer edit/autosave frequency rather than prompt size.
Idle / inference behavior
When the composer is idle:
- ProcMon shows no repeated global-state rewrite activity.
composer-prompt-drafts-v2does not change.
When Codex is executing/inferencing and the composer is not being edited:
- the draft watcher remains idle.
This suggests that the repeated writes are caused by composer draft persistence rather than model inference, MCP activity, or background heartbeat activity.
Additional observation: atomic rename failures
Most SetRenameInformationFile operations succeed.
However, occasional operations return:
ACCESS DENIED
after which Codex appears to clean up the temporary file.
This is secondary to the main problem: the primary issue is the high frequency of full-file rewrites.
Global-state size
Before investigation, .codex-global-state.json was approximately:
3.14 MB
A large prompt-history field (~1.35 MB) was removed as a diagnostic test, reducing the file to approximately:
1.19 MB
This substantially reduced the size of each rewrite, but did not remove the underlying behavior.
The composer autosave still rewrites the entire global-state file and backup.
Expected behavior
Saving composer drafts should not require repeatedly rewriting the entire global-state file and its full backup.
Possible approaches:
- debounce composer persistence more aggressively
- persist drafts only after user inactivity
- save on blur/thread switch/submit/shutdown
- store composer drafts in a separate small file/database
- update only the changed state instead of serializing the full global-state payload
- avoid rewriting
.bakon every small composer-state mutation
Actual behavior
Small composer edits trigger repeated full atomic rewrites of both:
.codex-global-state.json.codex-global-state.json.bak
This produces unnecessary write amplification and avoidable SSD wear.
Why this matters
This is not just normal chat/session persistence.
The observed write amplification is caused by the mismatch between:
- very small
composer-prompt-drafts-v2mutations - full ~1.25 MB primary rewrite
- full ~1.25 MB backup rewrite
Long editing sessions in the composer can therefore generate tens or hundreds of MB of writes from very small text edits.
Related issues
There are other reports of excessive Codex Desktop disk writes and repeated JSON rewrites, for example:
- #32496 - excessive SSD write churn from small JSON files
- #26401 - global-state cleanup/repopulation behavior
- #41081 - composer/send path still updates global-state and WAL files on Windows
- #38757 -
.codex-global-state.json/.bakdurability concerns
This report appears to describe a more specific trigger:
composer draft autosave -> full global-state + backup rewrite
What steps can reproduce the bug?
-
Start Codex Desktop on Windows.
-
Open an existing thread or a new thread.
-
Monitor:
C:\Users\<user>\.codex\.codex-global-state.json*with Sysinternals Process Monitor.
-
Leave the composer idle for several minutes.
Result:
- no repeated global-state writes
- no
composer-prompt-drafts-v2mutations
-
Start typing normally in the composer.
-
Observe repeated mutations to:
electron-persisted-atom-state -> composer-prompt-drafts-v2 -
At the same timestamps, ProcMon shows repeated full writes to temporary files such as:
..codex-global-state.json.tmp-<uuid>and
..codex-global-state.json.bak.tmp-<uuid> -
Each temporary file is then atomically renamed/replaced into:
.codex-global-state.jsonor
.codex-global-state.json.bak -
Stop typing.
Result:
- the draft mutations stop
- the repeated global-state rewrites stop
What is the expected behavior?
No response
Additional information
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing persistence for electron-persisted-atom-state -> composer-prompt-drafts-v2 and the .codex-global-state.json* files described in the report. Reproduce typing and idle behavior with Sysinternals Process Monitor, then identify why each small draft mutation rewrites both full files. Done means composer editing no longer causes repeated full primary and backup rewrites while draft persistence remains functional.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- electron
- Domain
- desktop, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100