Codex SQLite feedback logs can write ~640 TB/year and rapidly consume SSD endurance
Update at Jun 23, 2026: the following 3 PRs are merged, it could avoid 85% logs(feedback from my codex), so let me close this issue.
Thanks @jif-oai for the fix.
- https://github.com/openai/codex/pull/29432 (released in 0.142.0)
- https://github.com/openai/codex/pull/29457 (released in 0.142.0)
- https://github.com/openai/codex/pull/29599 (will be released in 0.143.0)
Simple Workaround from @beskay https://github.com/openai/codex/issues/28224#issuecomment-4778468005
- Quit codex
- Run this command:
sqlite3 ~/.codex/logs_2.sqlite "CREATE TRIGGER IF NOT EXISTS
block_log_inserts BEFORE INSERT ON logs BEGIN SELECT RAISE(IGNORE);
END;"
-------------------------------------------------------
Following is the original issue
Issue
Codex is continuously writing a large amount of data to the local SQLite feedback log database:
~/.codex/logs_2.sqlite~/.codex/logs_2.sqlite-wal~/.codex/logs_2.sqlite-shm
On my machine, after about 21 days of uptime, the main SSD has written about 37 TB. Process/file-level checks show Codex SQLite logs are the main continuous writer.
That extrapolates to roughly 640 TB/year. On a 1 TB SSD, that is about 640 full-drive writes per year. Some consumer SSDs are rated around 600 TBW, so this could consume roughly a full drive's warranted write endurance in less than a year.
Evidence1
A later snapshot makes the write amplification easier to see:
| metric | value |
| --- | ---: |
| current logs_2.sqlite file size | 1.2 GiB |
| current retained rows | 506,149 |
| total allocated row ids | 5,543,677,486 |
So the database currently retains only ~0.5M rows, while the SQLite AUTOINCREMENT counter has already advanced past 5.5B ids.
That is roughly a 10,000x gap between retained rows and historical inserted row ids. Even using the current ~1.2 GiB database size as a rough baseline, this points to 10TB+ scale historical log churn, before accounting for WAL, indexes, pruning, checkpoints, page rewrites, and filesystem/device-level write amplification.
Evidence2
Current retained rows in logs_2.sqlite:
| metric | value |
| --- | ---: |
| retained rows | 681,774 |
| estimated retained log content | 1,035.6 MiB |
Level distribution:
| level | estimated MiB | byte % |
| --- | ---: | ---: |
| TRACE | 732.5 | 70.7% |
| INFO | 266.5 | 25.7% |
| DEBUG | 30.6 | 3.0% |
| WARN | 5.9 | 0.6% |
Largest target+level pairs:
| target | level | estimated MiB |
| --- | --- | ---: |
| codex_api::endpoint::responses_websocket | TRACE | 527.4 |
| codex_otel.log_only | INFO | 141.2 |
| codex_otel.trace_safe | INFO | 121.2 |
| log | TRACE | 97.4 |
| codex_client::transport | TRACE | 60.1 |
| codex_core::stream_events_utils | DEBUG | 27.5 |
| codex_api::sse::responses | TRACE | 19.1 |
The top sources are mostly global TRACE logs, mirrored telemetry logs, and raw websocket/SSE payload logging. TRACE alone is about 70.7% of retained bytes. codex_otel.log_only + codex_otel.trace_safe add another 25.3%. Filtering these categories should remove roughly 96% of retained log bytes in this sample without fully disabling feedback logs.
<details>
<summary>Sanitized examples from the most frequent TRACE source: <code>target=log</code></summary>
These are high-frequency retained samples. Raw websocket/SSE payload bodies are intentionally not included because they may contain private conversation content.
128,764x TRACE log: inotify event: ... mask: OPEN, name: Some("ld.so.cache")
37,982x TRACE log: inotify event: ... mask: OPEN, name: Some("locale.alias")
23,843x TRACE log: inotify event: ... mask: OPEN, name: Some("passwd")
3,639x TRACE log: <tokio-tungstenite checkout>/src/compat.rs:131 AllowStd.with_context
3,505x TRACE log: <tokio-tungstenite checkout>/src/lib.rs:245 WebSocketStream.with_context
3,362x TRACE log: <tokio-tungstenite checkout>/src/compat.rs:154 Read.read
3,356x TRACE log: <tokio-tungstenite checkout>/src/compat.rs:157 Read.with_context read -> poll_read
3,230x TRACE log: <tokio-tungstenite checkout>/src/lib.rs:294 Stream.poll_next
3,227x TRACE log: <tokio-tungstenite checkout>/src/lib.rs:304 Stream.with_context poll_next -> read()
3,213x TRACE log: inotify event: ... mask: OPEN, name: Some("nsswitch.conf")
2,001x TRACE log: WouldBlock
1,217x TRACE log: Masked: false
1,169x TRACE log: Opcode: Data(Text)
1,169x TRACE log: First: 11000001
</details>
<details>
<summary>Sanitized examples from frequent INFO sources</summary>
The dominant INFO sources are mostly repeated OpenTelemetry mirror events. IDs are redacted.
843x INFO codex_client::custom_ca:
using system root certificates because no CA override environment variable was selected ...
334x INFO codex_otel.trace_safe:
session_loop{thread_id=<redacted>}:submission_dispatch{otel.name="op.dispatch.user_input" submission.id=<redacted> codex.op="user_input"}:turn{otel.name="session_task.turn" thread.id=<redacted> ...}
333x INFO codex_otel.log_only:
session_loop{thread_id=<redacted>}:submission_dispatch{otel.name="op.dispatch.user_input" submission.id=<redacted> codex.op="user_input"}:turn{otel.name="session_task.turn" thread.id=<redacted> ...}
332x INFO codex_otel.log_only:
session_loop{thread_id=<redacted>}:submission_dispatch{otel.name="op.dispatch.user_input_with_turn_context" submission.id=<redacted> codex.op="user_input_with_turn_context"}:turn{otel.name="session_task.turn" thread.id=<redacted> ...}
332x INFO codex_otel.trace_safe:
session_loop{thread_id=<redacted>}:submission_dispatch{otel.name="op.dispatch.user_input_with_turn_context" submission.id=<redacted> codex.op="user_input_with_turn_context"}:turn{otel.name="session_task.turn" thread.id=<redacted> ...}
</details>
Write amplification
The retained DB size hides the real write volume. In a 15-second sample:
| metric | before | after |
| --- | ---: | ---: |
| retained rows | 681,774 | 681,774 |
| max row id | 5,003,347,015 | 5,003,383,226 |
About 36,211 rows were inserted in 15 seconds, while retained row count stayed flat. This suggests continuous insert-and-prune write amplification: rows are inserted, indexed, written to WAL, then pruned.
Likely cause
The SQLite feedback log sink is installed with a global TRACE default:
Targets::new().with_default(Level::TRACE)
This persists all targets at TRACE level by default, including dependency/internal logs and large raw protocol payloads.
Proposed fix
Keep feedback logs enabled, but narrow what is persisted by default:
- Do not use global TRACE for the SQLite feedback log sink.
- Drop or raise thresholds for low-value dependency noise, especially
target=log,hyper_util, tokio-tungstenite internals, inotify spam, and low-level OpenTelemetry SDK logs. - Avoid persisting full raw websocket/SSE payloads by default. Store summaries instead: event kind, duration, success/error, token usage, and payload byte length.
- Avoid persisting mirrored
codex_otel.log_only/codex_otel.trace_safeevents unless they are explicitly useful for feedback debugging. - Add a global logs DB size/write cap. Per-thread caps are not enough when many threads/processes exist.
An optional escape hatch such as sqlite_logs_enabled = false would still be useful, but the main fix should be better default filtering.
Related issues and discussions
- https://github.com/openai/codex/issues/17320
- https://github.com/openai/codex/issues/24275
- https://github.com/openai/codex/issues/26374
- https://github.com/openai/codex/issues/22444
- https://github.com/openai/codex/issues/20563
- https://github.com/openai/codex/issues/27020
- https://github.com/openai/codex/issues/27911
- https://github.com/openai/codex/issues/21134
- https://github.com/openai/codex/pull/12969
154 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
cc @charley-oai @jif-oai since #12969 introduced the SQLite feedback log sink at TRACE level.
I pushed a minimal branch here:
https://github.com/1996fanrui/codex/tree/codex/reduce-sqlite-feedback-log-writes
The proposed patch does not disable feedback logs. It only changes the SQLite feedback log sink from global TRACE to this default filter:
In my local sample, the retained SQLite log content was mostly TRACE plus
codex_otelINFO mirror rows, so this should drop the high-volume low-signal writes while keeping INFO+ logs for core Codex targets.I tried to open an upstream PR, but GitHub returned:
Other possible fixes if the default-filter approach is not the preferred direction:
sqlite_logs_enabled = falseor a feedback-log-specific filter setting;This is a very serious bug, as it can not only cause login failures on Linux boxes if the system is rebooted while the disk is full, but Codex in
/goalmode will actively delete files and folders on your disk in a vain attempt to gain disk space. So the severity of this issue needs to be increased as data loss is possible when using Codex in this way.WTF this is ridiculous. PLEASE have more respect for your users.
I prepared a PR-ready branch against current
main, but upstream PR creation is still blocked for my account with:Branch:
https://github.com/Nicolas0315/codex/tree/codex/log-db-default-filter
Compare:
https://github.com/openai/codex/compare/main...Nicolas0315:codex/log-db-default-filter?expand=1
Proposed PR title:
Proposed PR body, following the recent Codex PR format:
Why
logs_2.sqliteis currently attached with a globalTRACEfilter in both the app server and TUI. On my Windows Codex app install, that persisted high-volume websocket internals and OTel mirror records into the diagnostic SQLite log DB:.codex/logs_2.sqlite: 729,575,424 bytes.codex/logs_2.sqlite-wal: 39,255,392 bytesTRACE: 123,026 rows / 269,065,577 estimated bytescodex_api::endpoint::responses_websocket,codex_otel.log_only,codex_otel.trace_safe, andlogThis matches the write-amplification report here and the Desktop launch failure mode in #27741. The change keeps diagnostic logs enabled, but makes the persisted SQLite sink less noisy by default.
What changed
log_db::default_filter()for the persistent SQLite log sink.INFO+by default instead ofTRACE.WARN+:codex_otel.log_onlycodex_otel.trace_safehyper_util::client::legacy::*logopentelemetry_sdkINFOlogs and dropped low-value OTel/mirror logs.Validation
git diff --checkjust test -p codex-state sqlite_sink_default_filter_drops_low_value_logsjust test -p codex-tui sqlite_sink_default_filter_drops_low_value_logscompiled the package, then exited with no matching tests.just fmtcompleted Rust/Python formatting, then failed on Windows in the Bazel buildifier step with[WinError 2].just test -p codex-app-serverrun compiled and executed tests but timed out after reporting831 passed, 4 failed, 6 skipped; the visible failures appeared unrelated to this log filtering change, including a skills fixture warning count mismatch.Here I have made two scripts which can serve as temporary mitigations for the WAL issue until OpenAI fixes it.
The first script trims the WAL while Codex processes are running:
To run as a cron job:
Note that the main table is trimmed, but there might be other tables which still accumulate data over a much slower period of time, requiring the script below.
The second script deletes the log and WAL files and kills all running Codex processes in order to immediately free disk space:
plz fix
Additional macOS /
codex-cli 0.141.0evidence from a local audit, checked again on 2026-06-20 UTC:openai/codexmain still attaches the SQLite log DB layer withTargets::new().with_default(Level::TRACE)in both app-server and TUI. The two public branches that switch to a lower persisted-log default both still apply cleanly to current main.~/.codex/logs_2.sqliteis 2.2 GiB, with ~74% freelist/free pages and no triggers.PRAGMA auto_vacuumis alreadyINCREMENTALon this DB, which is helpful for new maintenance behavior but did not shrink the existing old file; existing installs still need a safe compaction/quarantine path.MAX(id)advanced by 30,759. Retained rows in that interval were dominated by TRACE/INFO fromcodex_api::endpoint::responses_websocket,codex_api::sse::responses,codex_otel.log_only,codex_otel.trace_safe, and rawlog.codex exec --ephemeral --sandbox read-onlyprompt returningOKadvancedMAX(id)by 46,795 over ~21 seconds. Retained rows again concentrated in websocket/SSE TRACE and OTel mirror INFO rows.This supports the same conclusion as the existing reports: visible DB size is not the whole cost, because high insert/prune churn continues even when file size is stable or mostly freelist. A SQL trigger can reduce stored rows, but it happens after event formatting/queueing and is therefore only a stopgap.
Low-regression fix shape I would recommend:
VACUUM/recreate/move-aside path.The log DB should have an explicit byte budget and retention policy. Durable usage/diagnostic events can stay queryable, while websocket/SSE TRACE payloads need sampling, level caps, and rotation independent of the state DB. A startup receipt with effective log level, DB byte cap, WAL checkpoint policy, and dropped-row count would make write pressure visible before SSD wear becomes the signal.
---
_Generated with ax._
Additional native Windows check against current
main:63f009e9dad2e70454b7ed6434d8aa28dfb52b51Current source still attaches the persistent SQLite log layer with a global TRACE filter in both app-server and TUI:
codex-rs/app-server/src/lib.rslog_db::start.with_filter(Targets::new().with_default(Level::TRACE))codex-rs/tui/src/lib.rslog_db::start.with_filter(Targets::new().with_default(Level::TRACE))I also checked the current log sink implementation:
codex-rs/state/src/log_db.rsfeedback_log_body, queued, then inserted by a background task.opentelemetry_sdkTRACE/DEBUG, which helps one specific noisy target.codex-rs/state/src/runtime/logs.rsThat means DB size or retained row count can stay stable while insert/prune churn continues.
Local aggregate-only measurement from
.codex\logs_2.sqliteover 15 seconds, without reading log bodies:MAX(id)before: 191,131,613MAX(id)after: 191,131,862MAX(id)delta: 249 rows inserted in 15sTop retained target+level groups in this Windows sample were still dominated by the same categories already reported here:
codex_api::endpoint::responses_websocketTRACEcodex_otel.log_onlyINFOcodex_otel.trace_safeINFOcodex_core::stream_events_utilsINFOcodex_client::transportTRACErmcp::serviceTRACEcodex_api::sse::responsesTRACElogTRACEThis reinforces the earlier point: visible DB growth is not a reliable proxy for write pressure. Even with a stable retained row count, the append-and-prune path is still doing work. The low-risk patch shape still looks like filtering before formatting/queueing/inserting, not only pruning after insert.
I also rebuilt a narrow local candidate patch against the current
origin/mainhead:f774455(code-mode: linearize cell terminal state (#29286))codex_state::log_db::default_filter()Targets::new().with_default(Level::TRACE)WARN+INFO+for core Codex targets (codex_api,codex_app_server,codex_core,codex_mcp,codex_state,codex_tui)WARN+(codex_otel.log_only,codex_otel.trace_safe,hyper_util,log,opentelemetry_sdk)Local validation:
cargo test -p codex-state sqlite_sink_default_filter_drops_low_value_logs-> 1 passedcargo test -p codex-state log_db-> 7 passedcargo check -p codex-app-server -p codex-tui-> passedcargo fmt --check-> passed; stable rustfmt emitted repo-config warnings thatimports_granularityis nightly-onlygit diff --check-> passedPer
docs/contributing.md, I am not opening a PR unless invited, but this latest local patch is PR-shaped if maintainers want this direction.I hope the developers see this issue.
Shame on such low software quality with such high memory prices and SSD cost...
Additional macOS / Codex Desktop data point.
I checked this on my local machine with Codex Desktop running continuously. I did not read
feedback_log_body; only aggregate fields were queried.Environment:
codex-cli 0.142.0-alpha.6~/.codex/logs_2.sqliteBefore mitigation, the retained row count stayed stable, but
MAX(id)kept advancing:The retained log distribution was dominated by the same categories reported here:
As a temporary local mitigation, while keeping Codex running, I added a SQLite
BEFORE INSERTtrigger to drop the noisiest low-value rows:After installing the trigger, the same 20-second sample dropped sharply:
This is only a workaround. It reduces SQLite insert/prune churn, but it is not a proper fix because Codex may still format/queue log events before SQLite rejects them. The upstream fix should still filter before formatting/queueing/inserting, ideally with a documented config kill-switch or log-level setting for the SQLite diagnostic sink.
Here is how I fix it on my Win11 PC:
python -c "import sqlite3, pathlib; p=pathlib.Path.home()/'.codex'/'logs_2.sqlite'; con=sqlite3.connect(p); con.execute('CREATE TRIGGER IF NOT EXISTS block_log_inserts BEFORE INSERT ON logs BEGIN SELECT RAISE(IGNORE); END;'); con.commit(); con.close(); print(p)"
And to verify it, exe this:
python -c "import sqlite3, pathlib; p=pathlib.Path.home()/'.codex'/'logs_2.sqlite'; con=sqlite3.connect(p); print(con.execute('SELECT name, tbl_name FROM sqlite_master WHERE type=? AND name=?', ('trigger','block_log_inserts')).fetchall()); con.close()"
I made a small unofficial tool for running community-found Codex workarounds:
https://codexfixes.com
Run it with:
So we can stop checking issue threads every day for months and just patch the annoying stuff when the community finds a workaround.
Would creating a ramdisk and symlinking it there alleviate the issue temporarily?
@zhuhaow This is a useful idea, but I’d strongly suggest avoiding
@latestin the recommended command.Because this tool runs local code and modifies
~/.codex, the supply-chain risk is higher than a normal informational CLI. A safer default would be to recommend a pinned version, for example:Yeah, that is a very fair point, and I did think about this tradeoff.
The reason I’m currently recommending @.***` is that Codex keeps introducing new bugs, and the fixes here are meant to be a moving set of community workarounds. If users pin one version, they still have to keep checking GitHub issues, npm versions, or this repo to know when a new workaround exists, which is exactly the thing I’m trying to avoid.
That said, I agree the supply-chain risk is real, especially because this tool runs locally and touches
~/.codex. Right now I’m using npm provenance / attestations and the release is built through GitHub Actions, but I’m definitely open to better ideas here.@elliexcoding A ramdisk could reduce SSD wear by moving the SQLite DB/WAL writes off disk, but it does not reduce the underlying log event churn.
It also requires very careful handling. Since SQLite is in WAL mode, you have to symlink logs_2.sqlite, -wal, and -shm together. More importantly, if Codex is already running, it will keep writing to the original disk files via existing file handles until the process is restarted.
For always-on dev machines, since Codex continuously prunes old rows to cap the DB size at ~228MB, a ramdisk won't necessarily fill up indefinitely. However, it changes the failure mode into wasting RAM capacity and CPU cycles on ghost churn (formatting and syncing hundreds of trace rows/sec in memory) rather than fixing the root cause.
@zhuhaow
I don’t think
@latestis inherently wrong, and I agree the UX is elegant. Floating versions are common in practice, including in company tooling, because they make updates easy.The distinction I’d draw is between discovery and local mutation.
For discovery,
@latestseems acceptable:Output example:
But for applying a workaround that executes local code and modifies ~/.codex, I’d still prefer the docs to recommend a pinned version and explicit issue id:
That keeps the “don’t make users track issue threads” benefit, while avoiding the habit of running whatever the newest package version is against a sensitive local directory.
So maybe the default flow could be:
@latest doctorto discover available fixes.I would probably change to this behavior,
User install with npx codex-fixes
Every time it runs, it will check if there is a new version, and propose user to update, with the new fixes listed as information.
I also provide document to run it with npx @.***, but do not do it as default recommendation.
Looks like this is already being worked on here: https://github.com/openai/codex/pull/29432
Additional macOS Desktop reproduction data from an affected machine. This looks like the same insert/prune churn, and the open PR #29432 appears aimed at the dominant hot path in this sample.
Environment:
Visible files at
2026-06-22T13:32Z:lsofshowed the livecodexapp-server process holding the DB, WAL, and SHM files open. I did not find a deletedlogs_2WAL/SHM handle being held open on this machine.SQLite snapshot:
The large
freelist_countis notable:224,833 * 4096is about 878 MiB of freelist pages, which explains why the DB file is ~1.2G even though retainedestimated_bytesis ~181 MiB. The retention delete/prune loop appears to leave a large file behind unless a reclaim operation happens.Retained rows by level:
Top retained targets by estimated bytes:
The top three targets (
responses_websocketplus the twocodex_otelmirror targets) account for about 82.6% of retained estimated bytes in this sample, so #29432 should remove most of the retained-byte hot path here.Timed live sample during ordinary Desktop use:
So
MAX(id)advanced by 3,001 in 30 seconds while retained row count stayed flat, which is consistent with continuous insert + prune rather than simple growth.Rows still retained from that 30s window shortly after sampling:
Useful takeaways from this machine:
rmcp::service,codex_client::transport,codex_mcp::connection_manager,log,codex_api::sse::responses) that may be worth covering with a SQLite-sink-specific default filter or global write budget.Independent reproduction on Windows 11 (consumer ~600 TBW NVMe), with two additions beyond the write-volume story.
Corroboration:
logs_2.sqlitereached ~989 MB; lifetime autoincrement = 43.9M rows in 32 days (~1.35M/day), with TRACE ≈ 74% of bytes, then thecodex_otel.log_only/codex_otel.trace_safeINFO mirror — matching @1996fanrui's filter analysis. Biggest byte sources:codex_api::endpoint::responses_websocketandcodex_client::transport. Per #17320,RUST_LOGis ignored by this sink (confirmed here as well).(1) The file never shrinks after retention deletes it. Pruning is time-based (
DELETE FROM logs WHERE ts < ?), so ~99.9% of those 43.9M rows are already gone — yet the file stays ~1 GB because 231,446 / 253,293 pages (91.4%) sit on the freelist.auto_vacuum = INCREMENTALis set on the DB, butPRAGMA incremental_vacuumis apparently never run, so freed pages accumulate instead of being returned. Worth pairing the default-filter change with a periodicincremental_vacuum(or a size cap) — otherwise existing installs stay permanently bloated even after the write rate is fixed.(2) Verified partial mitigation users can set today:
OTEL_TRACES_SAMPLER=always_offis honored by the binary (it's parsed; the valid values are enumerated in the build) and removes thecodex_oteltrace mirror. It doesn't touch the TRACE bulk (that needs the filter fix / #17320), but it's a safe env-only knob that complements the tmpfs / insert-trigger workarounds above._(Observed on a customized build reporting v26.616.x; the affected targets/subsystem are identical to stock Codex and the symptom matches this issue exactly, so sharing as corroboration rather than as authoritative absolute numbers.)_
1.5TB/day of useless autodeleted writes is totally unacceptable. Dead macbook after 1 year.
Tried putting those sqlite files immutable but codex won't start without them.
Putting logs_2.sqlite* in a ramdisk works though;
I’ve confirmed this on my Mac too.
I’m on macOS 15.7.7 with Codex 26.616.51431.
~/.codex/logs_2.sqliteis already 113M, and SQLite showspage_size=4096,page_count=25862, andfreelist_count=9152, so there is already a significant amount of free space trapped inside the file.What convinced me this is the same issue is the row churn:
MAX(id)=34,277,360with only31,405retained rows, and over two 60-second samplesMAX(id)increased by 3774 and 3385 (~ 60 writes per second) while retained rows stayed roughly flat. That looks like continuous insert-and-prune logging, not normal low-volume diagnostics.I’m happy to share the exact commands I used if that would help, but the short version is that this reproduces on macOS for me as well.
Looks like I’m affected by this too. During a 1–2 hour Codex session, Activity Monitor showed that the
codexprocess had written about 50 GB of data. That seems unusually high and very similar to the behavior described in this issue.macOS + Codex app
Here's a quick fix to prevent the writes. First quit codex, then add a SQLite trigger that silently ignores new inserts into the diagnostic logs table:
After restarting Codex, logs_2.sqlite-wal stopped growing for me, and PRAGMA wal_checkpoint(TRUNCATE); returned 0|0.
To undo,
@almanaculum
Small correction: the undo command should probably be:
The backslash form in the comment may confuse shell parsing.
I also have two concerns/questions about this workaround:
VACUUMrewrites the database, so on already-largelogs_2.sqlitefiles it may itself cause a sizable one-time disk write and require enough free temporary space. Do you think the safer recommendation should be to add the trigger first, verify WAL growth stops, and only then optionally runDELETE/VACUUM?@Key-Zzs
Fair points. I copy-pasted, and the
\ngot lost there, and the DELETE could leave empty pages that the vacuum would end up copying.Also yes, there's no guarantee that Codex won't clobber the trigger in the next update, or that it may need to be undone before updating.
Adding a Windows Codex Desktop data point to this issue.
Environment
OpenAI.Codex_26.616.6631.0_x64__2p2nqsd0c76g0codex.exe app-server --analytics-default-enabledRUST_LOGin the shell environment:warn~/.codex/config.toml: no explicittrace,RUST_LOG, or log-level setting foundFiles observed
SQLite metadata:
The log table currently retains around 71k rows, while
sqlite_sequenceforlogsis above 18.5 million, which suggests heavy historical insert/prune churn even though the retained row count is much smaller.Continuous write sampling
Filesystem metadata sampling over 30 seconds showed
logs_2.sqlite-walLastWriteTimeUtcchanging about every 2 seconds. The WAL size was sometimes stable, but the timestamp kept advancing, consistent with ongoing WAL writes/checkpoint activity.A read-only SQLite sample over 30 seconds:
A second read-only verification sample over 10 seconds:
Dominant recent targets
Recent 10-minute distribution:
Top TRACE targets in that window:
Recent
target=logTRACE bodies are dominated by low-level websocket/tungstenite entries such as:Some
codex_api::endpoint::responses_websocketTRACE entries are large and appear to include raw-ish response payloads such asresponse.completeddata. I am intentionally not pasting raw payload bodies because they may contain private conversation content.Process mapping
All recent rows in the sampled window used:
That PID maps to:
Expected behavior
With
RUST_LOG=warnand no explicit trace logging configured, Codex Desktop should not continuously persist dependency/internal TRACE logs and large websocket/SSE payloads intologs_2.sqlite.Actual behavior
Codex Desktop app-server continuously inserts TRACE rows into
logs_2.sqlite/WAL during normal use. The dominant sources are low-level websocket/tungstenite logs plusresponses_websocket/SSE traces. This creates sustained local SQLite write activity and potential disk wear/performance impact.Please treat this as a user-impacting issue. Even if the exact SSD endurance impact varies by machine, users should not have to absorb continuous avoidable disk writes from TRACE/debug logging during normal Codex Desktop use. It would be very helpful for Codex to prioritize stopping this unnecessary local disk write amplification.
Suggested fix
Please avoid a global TRACE default for the SQLite feedback log sink, or at least filter out low-value dependency targets such as
target=log, tokio-tungstenite internals,hyper_util, raw websocket/SSE frames, and large raw response payloads. A configurable local opt-out or size/write cap for the SQLite feedback log would also help.holy f#c% this thread is confusing, so what is the actual fix script or command?
There’s no fix yet. Every option is just a temp hack.
If you want it to stop killing your ssd put it in a ramdisk until OpenAI fixed it properly.
Why was this closed as completed? @1996fanrui
@r00q
They merged:
https://github.com/openai/codex/releases/tag/rust-v0.142.0
Released!
Post-release macOS data point: I can still reproduce persistent SQLite log churn after upgrading to
rust-v0.142.0.Environment
26.616.71553, build4265codex-cli 0.142.0codex-cli 0.142.0/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled7763, startedTue Jun 23 10:17:10 2026RUST_LOG: empty~/.codex/config.toml:[analytics] enabled = false0logs_2.sqlitejournal mode:walFiles observed
The active app-server process is holding the DB/WAL/SHM files open.
Read-only 60 second sample
Sample window:
SQLite metadata before/after:
So the retained row count stayed flat, but
sqlite_sequence/max_idadvanced by1,616in about 60 seconds. This looks like continued insert-and-prune churn.File mtimes also moved during the sample:
The WAL size stayed stable at about 4.9 MB, so file size alone hides the ongoing write activity.
Recent persisted targets
Rows in the last 60 seconds:
TRACE targets in the last 5 minutes:
Interpretation
#29432appears to have helped:codex_api::endpoint::responses_websocketis much lower than before.However,
#29457does not appear to fully solve the persistent SQLite churn in this app build/runtime. The release note says noisy persistent log targets were filtered, and the PR says bridgedtarget=logevents should be excluded from the SQLite sink, butTRACE target=logis still the dominant persisted target here.Expected behavior: after
rust-v0.142.0, Codex should not continuously persist high-frequencyTRACE target=logrows intologs_2.sqliteby default.I am intentionally not pasting raw
feedback_log_bodycontents because they may contain private conversation or tool data.I can confirm this is still happening on my side (Windows) and looks very similar to what #28224 captured.
My environment:
C:\Users\User%USERPROFILE%\.codex\logs_2.sqlite: 6,542.19 MB%USERPROFILE%\.codex\logs_2.sqlite-wal: 101.82 MBDB analysis from my machine:
logstable has substantialTRACE/DEBUGactivity.targets are also websocket/SSE/otel/log-style noise channels (similar pattern to the issue body).CrystalDiskInfo snapshot (
CrystalDiskInfo_20260623102934.txt):So this is very consistent with app-level SQLite feedback-log churn rather than SSD health failure.
I also had to apply the known safe non-destructive workaround trigger:
CREATE TRIGGER IF NOT EXISTS block_log_inserts BEFORE INSERT ON logs BEGIN SELECT RAISE(IGNORE); END;(no sessions deleted), to keep this from continuing to explode.
Given #28224 is already showing evidence from multiple platforms and now closed after
Stop logging every Responses WebSocket event+Filter noisy targets from persistent logs, would be useful to get another Windows data point with these exact local sizes.still happen on macos! should reopen this issue
Codex estimated: "this regression plausibly burned low-single-digit millions of dollars of SSD endurance across users during the March-June Window," assuming only 5% of users had the write intensity of the reporter, or: "If affected users averaged 50% of that rate, the estimate rises to the low tens of millions."
@jif-oai Please add a permanent regression test that bounds persistent local writes. Maybe #29432 and #29457 solve this issue, or maybe they don't. But, OpenAI should make sure this never happens again by proactively catching similarly damaging bugs in the future whether it has to do with log writes or anything else.
@jif-oai Please also add regression tests for prioritize reports of runaway CPU/memory/disk usage, across macOS, Windows, and Linux. There are many users experiencing CPU/memory runaway on long ignored bugs, which is unnecessarily burning loads of electricity, degrading battery life, and thermal stress is probably causing some level of hardware damage on some machines unnecessarily constantly running at throttling temperatures.
_Note: Codex's estimate is based on ~ 3 million weekly active Codex users, guessing 50% of them were affected, 95% on SSDs, 75% on the affected version, 5% having the intensity reported here, with $0.13 cost per TBW written to SSDs._
Still seeing ~100KB/sec writes on MacOS using latest version 26.616.71553. I imagine a class-action lawsuit is coming.
The most aggravating aspect of this is that this is burnt on useless crap like the /feedback submission data.
Let that be opt in. Disable all that telemetry by default.
Put that app on a diet; it’s so bloated.
Still experiencing write amplification on Windows with codex 0.142.0
Environment:
%USERPROFILE%\.codex\logs_2.sqliteCurrent database state (2026-06-23 15:17):
This means ~36.7 million rows were historically inserted, but 99.8% were pruned, leaving only 62k rows. The continuous insert-then-prune pattern is causing significant SSD write amplification.
The two merged PRs (#29432, #29457) may have reduced log volume, but the core write amplification issue persists on my system after upgrading to 0.142.0.
And just on that damage part - many devices cannot just replace the disk as it's soldered, so the lost value isn't merely ``
WASTED_TB_written × (SSD_cost / SSD_endurance_TBW)`, but instead need to use`COMPUTER_cost`` in that formula as it's a non-replaceable component.https://github.com/openai/codex/releases/tag/rust-v0.142.0 has the fix in the "Chores" section... 👀
I’m still seeing significant SQLite log churn on macOS with Codex 26.616.71553.
In a ~10 minute sample:
So Codex appears to have inserted around 146k rows in ~10 minutes, while only ~1.5k rows were retained. That looks like the same insert-and-prune write amplification pattern described in this issue, although at a lower rate than the original report.
Windows PowerShell One-Line Fix
For Windows users, here's a cleaner PowerShell version of the temporary fix.
Environment Verification
I can confirm this issue still exists on Windows 11 (even after
rust-v0.142.0):logs_2.sqlite= 2.6 GBmax_idhas reached 36M+ (~593x amplification)Quick Fix (Recommended)
Add trigger to block writes
Verify trigger is installed
Expected output:
Undo the fix (restore logging)
If you need to restore Codex's logging functionality:
Advantages
Compared to other community solutions:
DELETEorVACUUM, avoiding potential extra disk writes from rewriting large filesImportant Notes
logs_2.sqliteOptional: Clean Up Existing Logs (Advanced Users)
If you want to reclaim disk space, after adding the trigger you can execute cleanup (requires stopping all Codex processes first):
⚠️ Warning: The
VACUUMoperation rewrites the entire database file, which may take considerable time on large files and produce a one-time large amount of disk writes.Verify Effectiveness
After applying the fix, you can verify writes have stopped:
If the trigger is working,
Deltashould be 0 or close to 0.---
Hope this helps other Windows users!
just link two more open issues for visitors coming here:
~/Library/Application Support/com.openai.codex/web/Crashpad/pending
com.openai.codex.code_sign_clone
Hey @DmitriyTor , thanks for testing it with the latest version, have you killed all old version codex?
This issue is not fixed. On ubuntu, using
sudo iotop -aoPI can see that Codex writes around 10MB of data per second, which is around 315TB per year.I am using version 0.142.0
Hey @beskay , thanks for testing it with the latest version!
Same question with the last one, have you killed all old version codex?
Yes I deleted all old versions. The second I send a message to Codex, it starts writing around 10MB/s of data to my disk
edit: To be more clear, I deleted all prior releases in
~/.codex/packages/standalone/releases/Yes I deleted all old versions. And tested for 20 minutes session second time
In a ~20 minute sample:
So Codex appears to have inserted around 463k rows in ~21 minutes while only retaining ~3.5k rows. That is roughly 370 inserted rows/sec
There are also intervals where retained rows stay completely flat while max rowid grows rapidly. For example, around 11:39:48–11:40:13, retained rows stayed at 230,022 while max rowid increased from 341,155,283 to 341,202,311.
Quick workaround until it is fixed:
After this my disk usage went to almost zero. Only ~5mb per minute in read/writes.
Still reproducible on Windows Codex Desktop 26.616.9593.0 / CLI 0.142.0
I tested the current Windows Codex Desktop build after the
rust-v0.142.0fixes (#29432 and #29457). The issue appears reduced, but not fully fixed on this environment.Environment:
OpenAI.Codex_26.616.9593.0_x64__2p2nqsd0c76g026.616.9593.0codex.exebinary string contains:0.142.0codex.exe app-server --analytics-default-enabledOpenAI.Codex_26.616.9593.0package pathblock_log_insertsworkaround trigger is installed inlogs_2.sqliteCurrent DB snapshot:
Retained level distribution:
Read-only 60 second sample:
Rows inserted during that sample (
id > before_max_id):Top inserted targets during that sample:
Interpretation:
codex_api::endpoint::responses_websocketpayload churn.target=logevents from the persistent SQLite sink in this Windows Desktop runtime.max(id)andsqlite_sequenceadvanced, so insert-and-prune churn is still happening.I intentionally did not include raw
feedback_log_bodyvalues because they may contain private conversation or tool data.Codex analyzed the disk usage and says this bug cost me $38.64 in drive value of my Samsung 990 2TB NVMe. Codex resets would be nice. It would be nice if these ones didn't expire in 30 days though, because I already have 2 banked and probably wouldn't get to use the new ones.
@Bandersnatch0x I just cut a new alpha with one more patch, could you test it on your machine to see the impact?
v0.143.0-alpha.6Please don't change this behavior, this is important to my agent workflows. I have configured my agents use the sector write counts on my Samsung 990 EVO 2tb as an immutable counter as part of their coordination. Changes to this behavior would very likely break this workflow. If this is to be changed please enable a option to re-enable this expected behavior. Thanks.
is this ok with the windows or mac app ?
not just cli ?
Thanks
It is just an alpha CLI. It will come to the App soon
awesome
Just in case this doesn't get fixed with the latest alpha release...
I’m seeing what looks like the same continuing underlying SQLite churn pattern on macOS, though my setup differs slightly: I have not specifically disabled analytics/plugins, and the running process is
codex app-server --analytics-default-enabled.I posted the fuller diagnostic here: https://github.com/openai/codex/issues/29612#issuecomment-4780728496
Summary of my repro:
Over a 5-minute idle sample, with Codex Desktop open in the background but not actively used:
The DB was healthy and compacted beforehand, so this did not appear to be leftover pre-fix bloat:
The exact sampled ID window showed retained rows dominated by
TRACE target=log:All retained rows from that sampled window belonged to the same app-server process.
So this looks like the same post-0.142.0 behavior: file size may remain bounded, but the app-server still continuously inserts and prunes persistent SQLite log rows while idle, mostly
TRACE target=log, despiteRUST_LOG=warn.@mdbecker would you mind trying your setup on the alpha?
logs_2.sqlite still receives high-frequency TRACE writes on macOS Desktop / CLI 0.130.0 after #28224
I am seeing behavior that appears to match or partially persist after #28224.
Environment
codex-cli 0.130.026.616.71553~/.codex/logs_2.sqlite~/.codex/logs_2.sqlite-wal~/.codex/logs_2.sqlite-shmCurrent local database state
File sizes:
Schema:
At one sample point:
This large gap between
max(id)and retained rows looks similar to the insert/prune write amplification described in #28224.Short sampling evidence
In a 15 second sample during normal active use:
The retained row count only increased by 56 rows during the same sample.
Level distribution
Largest target / level pairs
Expected behavior
After the fixes referenced in #28224, the persistent SQLite log sink should no longer keep writing high-frequency TRACE logs during normal active use, especially for websocket/SSE response paths.
Actual behavior
~/.codex/logs_2.sqlitestill appears to receive hundreds of inserted log rows per second during normal active use, withTRACEandresponses_websocketstill dominating retained bytes.Could you confirm whether Codex Desktop app
26.616.71553/ CLI0.130.0includes the #28224 fixes, and whether this remaining write rate is expected?@jif-oai Tested
v0.143.0-alpha.6on Windows 11 against0.142.0as baseline. Results below.Test setup
wire_api = "responses") — triggers the same WebSocket/SSE code pathsCODEX_HOMEper version, identicalconfig.tomlandauth.jsoncodex app-server --listen ws://127.0.0.1:PORTidle for 25 seconds, then killedsqlite_sequence,COUNT(*), level/target distribution fromlogs_2.sqliteBoth test databases were clean before starting (no triggers, no prior rows).
Results (25-second idle sample)
| Metric | 0.142.0 | 0.143.0-alpha.6 |
|--------|---------|-----------------|
| Total rows (seq) | 70 | 70 |
| INFO | 31 | 31 |
| TRACE | 21 | 24 |
| DEBUG | 12 | 10 |
| WARN | 5 | 4 |
| ERROR | 1 | 1 |
|
target=logTRACE | 12 (17%) | 0 ✅ ||
codex_otel.*mirror | 0 | 0 |TRACE breakdown
0.142.0: 12×
target=logTRACE + 9× other TRACEalpha.6: 0×
target=logTRACE + 24×hyper_util::client::legacy::pool/client/connect::httpTRACEWhat this confirms
target=logTRACE events are completely eliminated (12 → 0)codex_otel.*mirror rows, noresponses_websocketTRACE in either versionhyper_utilTRACE noise persists (24 rows) but is much lower volume than the bridge spam wasCaveat
This is an idle test — no actual API calls flowed through the app-server. The real write amplification reported in #28224 happens during active
responses_websocket/SSE streaming. pwukun reported ~60% of runtime inserts came fromtarget=logTRACE on0.142.0; those should all be gone now. Would be great if someone running the Desktop app (whereapp-serverprocesses live traffic) can confirm the runtime numbers.Raw verification
Happy to re-test with a different workload or provide the raw SQLite dumps.
I also tested the
0.143.0-alpha.7standalone app-server binary, but I do not consider this equivalent to the Desktop GUI repro. In that standalone run, the 5-minute idle sample produced only 45 inserted IDs, or0.15/sec, and retained rows increased by 45, so I did not observe the same insert/prune churn there. However, I could not test a signed Desktop GUI alpha because the GitHub release asset appears to provide standalone binaries rather than a signedCodex.appbundle.UPDATE: I also tested the bundled
0.142.0app-server standalone as a control. It also did not reproduce the GUI idle churn: 69 inserted IDs over 5 minutes, or0.23/sec, with retained rows increasing by 69. This suggests the ~10/sec insert-then-prune churn I’m seeing is specific to the signed Desktop GUI-launched path, or to something the GUI/frontend causes the app-server to do while idle, rather than the bare app-server process by itself.UPDATE 2: I also measured the signed 0.142.0 Desktop GUI while it was actively running a task, as a comparison to the idle repro. The churn increased from ~9.92 inserted IDs/sec while idle to ~21.49 inserted IDs/sec during active use. Retained row count still stayed effectively flat, so this continues to look like insert-then-prune churn. The active run also showed a small number of large TRACE transport rows, including codex_client::transport at ~9.8 MiB body_kib across 11 rows. That did not appear in the idle-only sample. This reinforces that the signed Desktop GUI path is still persisting TRACE rows despite RUST_LOG=warn, and active tasks can produce both more rows and much larger persisted bodies.
If you let me know when a signed macOS app is available, I’d be happy to test it and rerun my diagnostics.
Is there a way to create a virtual drive or volume in Windows that acts like /dev/null?
I want any file written to this drive to be automatically discarded (effectively disappearing), so I can redirect my log files there.
https://www.ltr-data.se/opencode.html/#ImDisk + mklink the sqlite files there
@W944 do you know what I can do in linux? Maybe a memory map file? linking /dev/null fails (codex says database got corrupted)
/dev/shm is already a ram-only filesystem on linux, just symlink the 3 sqlite files onto there and you're good to go
/dev/null is a black hole - that's not the destination you want as codex still needs to write/read its crap in those sqlite files. Just that in the ramdisk it's all ephemeral.
Glad I don't vibe code much :)
btw is this resolved in the today's desktop app update?
I tested the current stable signed macOS Desktop app after updating and fully restarting Codex. The issue is improved compared with older versions, but high-frequency SQLite log churn is still reproducible during an active Desktop GUI session.
Environment
26.616.811504306codex-cli 0.142.0~/.codex/logs_2.sqlite30-second active-session sample
Immediately after restart, I sampled
max(id)from thelogstable:The retained row count stayed flat, so this still looks like insert-then-prune churn rather than normal retained-log growth.
File sizes at the same time:
New rows during the sample
For rows with
id > 19050825:The newest retained rows were still WebSocket internals bridged through
target=log, for example:So on the signed Desktop GUI path,
0.142.0still appears to persist high-volumetarget=logTRACE rows during active use. This seems consistent with the expectation that #29599 / the0.143.0line should remove the remaining bridgedtarget=logTRACE spam, but it is not fixed in the current stable Desktop build I received today.After updating the win-codex version to 81150 today(which winapp version is 26.616.10790.0 ), there are still issues. The self-check conclusion is as follows.
There are changes, but not the kind of changes that "improve to a safe level".
Based on our several rough samplings, it can be roughly calculated as:
| Time/State |
max_idIncrease | Approximately Equal to | WAL Change | Main Source | |---|---:|---:|---:|---|| Early update silent | +375 / 31.7s | ~12 lines/s | Size remains unchanged but mtime is updated |
tokio-tungsteniteTRACE || After one time | +442 / 34.5s | ~13 lines/s | Size remains unchanged but mtime is updated |
tokio-tungsteniteTRACE || Peak before/after version/restart | +28,053 / 33.7s | ~832 id/s | +3.88 MB |
tokio-tungsteniteTRACE || After restart | +46,083 / 32.6s | ~1,414 id/s | +5.60 MB | websocket/SSE/TRACE |
| Today's latest | +6,676 / 33.5s | ~199 id/s | WAL size remains unchanged, mtime is updated |
codex_app_server::outgoing_messageTRACE |So: Compared to the worst result yesterday, which was +28k to +46k in 30 seconds, this time today it has dropped to +6.7k in 30 seconds. It is indeed much smaller. **
But there are still two issues:
max_idis still increasing, the WAL modification time is still being updated, and TRACE is still being added to the database.Previously, it was mainly
tokio-tungstenite/ websocket-based trace; today, it has mainly become:The size of the new log entries added today is approximately 1.31 MB / 33.5 seconds, which is about 39 KB/s, equivalent to approximately 3.4 GB/day in terms of log content volume; the actual SSD write speed may be higher or lower due to SQLite/WAL/checkpoint/index factors.
Conclusion: The write volume has significantly decreased compared to yesterday's peak, but the problem has not disappeared. It is still not a normal low-frequency log behavior. **
This is honestly ridiculous. Did the Codex team’s architects or technical owners not consider the system-wide implications of this at all? What level of technical ownership is this?
An architect is supposed to think globally. Things like logging volume, default log levels, disk write amplification, WAL growth, log rotation, retention limits, high-frequency event streams, and long-running workloads should be almost reflexive considerations for experienced backend engineers.
A developer using a shared logging utility may not understand the full impact, but that is exactly why architects and responsible technical owners are supposed to provide guardrails and review the overall design. A shared logging system should make unsafe behavior difficult or impossible by default.
Persistent TRACE-level logging of high-frequency events without strict limits, sampling, rotation, retention controls, or disk-write safeguards is not an obscure edge case. It is a basic operational risk for any developer tool that can run continuously on users’ machines.
Yet this still happened in Codex. It is difficult to understand how this passed architecture review, long-running stress testing, and release quality gates.
If your architects are unable to identify risks like this, I would be happy to help review the design.
<img width="2172" height="724" alt="Image" src="https://github.com/user-attachments/assets/15975a0f-6a0c-47bf-b9e6-b42447b074f7" />
Probably the AI/LLM did the architecture, reviewed and approved it?
I can still reproduce significant
logs_2.sqlitewrite amplification on the latest available Codex Desktop build.Environment:
0.137.0app-server holdinglogs_2.sqlite, but it is now gone. Current writer is/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled.Current DB state:
~/.codex/logs_2.sqlite: 963 MiB~/.codex/logs_2.sqlite-wal: ~45 MiBRecent 15-minute retained log distribution:
Top recent targets:
codex_api::endpoint::responses_websocketTRACE: 5.84 MiBcodex_api::sse::responsesTRACE: 1.8 MiBcodex_mcp::connection_managerTRACE: 0.72 MiBcodex_core::stream_events_utilsDEBUG: 0.42 MiBlogTRACE: 0.38 MiB15-second samples after removing the stale old app-server:
id_delta=1895,count_delta=-90,wal_delta=0id_delta=2420,count_delta=89,wal_delta=0So 0.142.0 appears to reduce the worst behavior, but it does not fully stop persistent TRACE/streaming/MCP logging. The file size may look stable, but
MAX(id)keeps advancing quickly while retained row count stays roughly flat, which still indicates insert-and-prune write amplification.Expected behavior:
Still reproducing on 0.142.0 (which already ships #29432 + #29457) — macOS desktop app-server
Environment:
APPLE SSD AP1024Z, 1 TB26.616.81150(build 4306); its bundled binary reportscodex-cli 0.142.0Even on 0.142.0 — which already contains "Stop logging every Responses WebSocket event" (#29432) and "Filter noisy targets from persistent logs" (#29457) — the desktop
codex app-serverstill floods~/.codex/logs_2.sqlite:logsMAX(id)climbed 41,235 → 55,007 across a clean app restart while the retained row count stayed pinned at ~3,072 — i.e. the insert-and-prune churn described abovelogs_2.sqlite-walre-bloats to ~5 MB within seconds;PRAGMA wal_checkpoint(TRUNCATE)only clears it transiently while the app keeps writingSo on the macOS desktop path the 85% reduction doesn't appear to be enough yet — TRACE is still the overwhelming majority of persisted rows.
As an alternative to the tmpfs-symlink workaround, this stops the churn without losing useful logs (DEBUG/INFO/WARN still recorded):
(
RAISE(IGNORE)skips the row without consuming the AUTOINCREMENT counter.) After applying it the insert rate drops to ~0/s and the WAL stays at 0.I prepared a candidate fix, but this repository currently limits opening pull requests to collaborators, so I cannot open the draft PR directly from my fork.
Compare branch:
https://github.com/openai/codex/compare/main...ChiTienHsieh:codex/reduce-log-db-churn
Commit:
11722a0713 Reduce SQLite log churnWhat it changes:
TRACEtoINFO.OFFtargets forlog,codex_otel.log_only, andcodex_otel.trace_safe.tracing-logevents whose final tracing target islog, because the outer target filter can see the original log target before bridging.opentelemetry_sdkTRACE/DEBUGtimer/meta events.Validation:
git diff --checkcargo test -p codex-state filter_testsTRACE|logcount0inlogs_2.sqlite.TRACE|logcount0.Important caveat:
This is a Codex-generated fix and has not yet been reviewed by a human. The runtime smoke test was also performed by Codex on a macOS Apple Silicon machine. It appears to solve the reproduced local churn, but it needs maintainer/human review before being treated as correct upstream.
@ChiTienHsieh this matches what I'm seeing — the noise is essentially all
TRACE|log, so flipping the persistence default fromTRACEtoINFOshould address the bulk of it.As an independent data point on the same machine (macOS / Apple Silicon,
codex-cli 0.142.0desktop app-server): instead of patching the binary I added a sink-level block at the SQLite layer —After this, the insert rate drops from ~20.8 rows/s to ~0/s and
logs_2.sqlite-walstays at 0, whileDEBUG/INFO/WARNrows still persist — i.e. the sameTRACE|log = 0end state your patch reaches, just enforced from the DB side rather than the filter. So it's consistent thatTRACEis the entire problem and anINFOdefault would fix it at the source. Hope this helps the review.Please fix ASAP. Ssd prices aren't fun anymore.
The merged PRs (#29432/#29457/#29599) excluded noisy targets but left the root cause: the persisted sink is hardcoded to
LevelFilter::TRACE(state/src/log_db.rs), independent ofRUST_LOG. I've prepared a focused fix:CODEX_LOG_DB_LEVEL+[log] level.[log] persist = false/CODEX_LOG_DB=off.journal_size_limit+wal_autocheckpoint(logs DB only), startup + periodic best-effortTRUNCATEcheckpoint (was startup-only PASSIVE).Diff/branch for reference: https://github.com/denispol/codex/pull/1 — happy to open an upstream PR if the team wants it.
The problem still exist for codex-cli v0.142.2 on WSL2
I can reproduce this class of issue on macOS with a current Codex Desktop build, and I want to add that this has real SSD wear implications for normal users who would not notice the background write churn.
Environment:
/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabled~/.codex/logs_2.sqlitein WAL modeRUST_LOG=warnWhat I observed before applying any workaround:
logs_2.sqlite: about 110 MBlogs_2.sqlite-wal: about 5.1 MB during observationTRACEdominating recent rows. One sample showed approximately 1,582 TRACE rows from the app-server process in the last 60 seconds.WebSocketStream.with_context,Stream.poll_next,Read.read,received frame, and similar internals.logsautoincrement sequence had reached about 19.7 million inserted rows.Impact:
Expected behavior:
RUST_LOG=warnis present.Local mitigation I applied:
[analytics] enabled = falsein~/.codex/config.toml.TRACE,DEBUG, andINFOinserts intologswhile preservingWARN/ERROR.PRAGMA wal_checkpoint(TRUNCATE);.delta_ids=0, and the WAL stayed at 0B with stable mtime.Please treat this as a product bug, not just a diagnostic inconvenience. The app should not silently write high-frequency TRACE logs to user SSDs in production. Please clarify why this SQLite logging sink bypasses or differs from
RUST_LOG=warn, and what release will change the default behavior to prevent unnecessary SSD wear.Follow-up: I am requesting that OpenAI route this issue to the appropriate support/customer-success path for compensation or account credit, not only engineering triage.
This bug silently caused avoidable SSD writes on user hardware during normal Codex Desktop usage. The user did not opt into production TRACE-level SQLite persistence, and the process environment showed
RUST_LOG=warn. If the user had not manually inspected~/.codex/logs_2.sqliteand the WAL behavior, the background writes would have continued.I understand GitHub issues are primarily for engineering tracking, but please provide an official support route for affected paid users to request compensation/account credit for unnecessary hardware wear and time spent diagnosing/remediating this product defect. At minimum, OpenAI should:
RUST_LOG=warndid not prevent TRACE persistence into SQLite.This should not be treated as a harmless log-size issue; it caused real background disk writes on customer machines.
Apart from sqlite logs there are much more to optimize and at least to define one folder for temporary files in codex config. Right now there are at least three solder in the system where Codex write data (these stats from just a few sessions like for day):
<img width="422" height="514" alt="Image" src="https://github.com/user-attachments/assets/8ebb9f26-a324-4684-b930-eaa1ed0e9b95" />
<img width="304" height="565" alt="Image" src="https://github.com/user-attachments/assets/5d0dedf6-2bb5-4d93-bd87-995f5cdfdd72" />
<img width="298" height="208" alt="Image" src="https://github.com/user-attachments/assets/da28aa4a-754b-49f7-b5a2-d3f5b87b886f" />
@chensenxiang thanks — that lines up with my measurements too: TRACE persistence is the dominant churn source. The branch above moves that drop upstream into the SQLite sink (default
TRACE→INFOplus a sink-side guard) instead of relying on a local trigger, so INFO/WARN/ERROR still persist and full TRACE stays available viaRUST_LOG=traceon the file-log path.Tests pass locally:
Has Codex Desktop been fixed? It's been so many days already. Earlier they said it would still write to the hard drive like crazy even in silent mode, so I don't even dare to open Codex.
I can confirm this issue on Windows Codex Desktop.
Environment:
OpenAI.Codex_26.623.4041.0_x64__2p2nqsd0c76g0C:\Users\<user>\.codex\logs_2.sqliteC:\Users\<user>\.codex\logs_2.sqlite-walC:\Users\<user>\.codex\state_5.sqlite*I ran a 5-hour metadata-only monitor from
2026-06-26 09:40:45to2026-06-26 14:40:56.Results:
Codex.exewrote about13.4 GBduring the observed period.49 MB/min.231 MB/min.logs_2.sqlitefile size did not grow:2555.461 MB2555.461 MBlogs_2.sqlite-walbarely changed:36.926 MB37.150 MBHowever, SQLite metadata showed heavy churn:
logs.MAX(id)changed from1039968250to10479998498,031,599new row ids during the monitor window.93492to99594, so this looks like insert/delete/rotation/page churn rather than normal file growth.Top new log groups by row count:
TRACE codex_api::sse::responses:7705rowsTRACE codex_mcp::connection_manager:1263rowsTRACE log:1110rowsDEBUG codex_core::stream_events_utils:352rowsLargest group by estimated payload size:
TRACE codex_api::endpoint::responses_websocket:75rows, about60 MBThis makes the issue hard to detect by only watching file size: the SQLite file can stay stable while the app still writes heavily to disk.
I have not applied the SQLite trigger workaround yet, but my telemetry suggests that dropping or reducing
TRACElogging would likely reduce the write load significantly.This needs to be a critical priority. People should not have to resort to workarounds in order to preserve their hardware when utilizing this product. I have not used the CLI/Desktop app (and therefore also am not using my rate limit) for several days after confirming that I am impacted by this issue. We should be getting partial refunds or a non-expiring limit reset as compensation for this.
We're on day 4 of the last response here from OpenAI, when some mitigations were applied that had varying impact. I don't get it. I thought this would be a 5 alarm fire until completely fixed.
<img width="1448" height="1086" alt="Image" src="https://github.com/user-attachments/assets/6cd61a20-ceb7-46c7-a8a7-99e6d2ad4808" />
Releasing Codex with this bug is akin to medical malpractice; like a surgeon forgetting a scalpel inside a patient.
The bug destroyed my Samsung 980 SSD, data lost into the void.
<img width="1280" height="1169" alt="Image" src="https://github.com/user-attachments/assets/37713094-10c4-48cd-a132-622305a68233" />
I can still reproduce high-volume persistent SQLite feedback logging on my machine after updating Codex.
Environment:
Observed before mitigation:
I did not inspect or share feedback_log_body values because they may contain sensitive diagnostic or conversation-related content.
Temporary mitigation applied:
CREATE TRIGGER IF NOT EXISTS block_log_inserts
BEFORE INSERT ON logs
BEGIN
SELECT RAISE(IGNORE);
END;
Validation after mitigation:
row_count = 68719
max_id = 3604997
latest_log_time = 2026-06-28 22:32:48
logs_2.sqlite-wal = 12K
row_count = 68719
max_id = 3604997
latest_log_time = 2026-06-28 22:32:48
logs_2.sqlite-wal = 12K
row_count = 68719
max_id = 3604997
latest_log_time = 2026-06-28 22:32:48
This suggests the trigger successfully stopped inserts, but the underlying persistent logging issue still appeared present on my installed version before mitigation.
I'm pretty sure OpenAI employees don't care about customers' SSDs at this point.
Do what oorangee97 says 2 comments above the small DB change fixes it until we get a real fix. Codex did a great job of proving the issue was happening for me just by pointing it at this URL and asking for it to check if the issue is happening here.
OpenAI team,
What’s the process for receiving compensation for the verifiable damage done to my SSD ?
I made a small cross-platform workaround script for this issue.
It works on Linux, macOS and Windows.
Trigger used by default:
Requirement:
Bun already includes SQLite support through
bun:sqlite, so you do not need to installsqlite3separately if you run the script forcing Bun's built-in SQLite backend.Usage, block TRACE log default:
Check status:
Block all logs:
Unblock logs again:
This is only a workaround until there is an official fix.
codex-log-blocker-crossplatform.js Updated
Thanks @oorangee97 for sharing the initial trigger workaround idea, and thanks @daryll-swer / @chensenxiang for pointing out that periodically rebuilding/compacting the database is not ideal here.
@wilywork
VACUUM does result in more writes on the SSD; if the DB file is small enough, it's probably best to delete the entries but leave file size as-is rather than to rewrite on the SSD with VACUUM.
@daryll-swer is right that
VACUUMis counterproductive here — it rewrites the whole DB, so a periodic clean-and-VACUUM script trades the logging writes for VACUUM writes. It treats the symptom after the bytes have already hit the disk.It's cheaper to stop the rows from ever being written. A
BEFORE INSERTtrigger that dropsTRACEat the SQLite layer needs no cron, no cleanup, and no VACUUM:On macOS / Apple Silicon,
codex-cli 0.142.0desktop, this takes the insert rate from ~20.8 rows/s to ~0 and keepslogs_2.sqlite-walat 0, whileDEBUG/INFO/WARNstill persist.RAISE(IGNORE)skips the row without consuming the AUTOINCREMENT counter, so there's nothing to clean up later. It survives until the next time Codex re-creates the DB (e.g. rotation to a newlogs_N.sqlite), at which point you'd re-apply it — or, better, the upstreamTRACE→INFOdefault fix lands and none of this is needed.Thanks everyone for the discussion, I took in all your suggestions and wrote two simple Python scripts. You can run them in PowerShell, and for the second one you need to wait 60 seconds to get the final result.
After testing this on Windows / Codex Desktop, the result looked good:
Trigger installed: codex_block_trace_logs
During a 60-second observation window:TRACE did not increase; it actually decreased from 23159 to 23138 due to old-row retention/rotation
INFO / DEBUG / WARN continued to be written normally
logs_2.sqlite-wal stayed around 4.16 MB and did not keep growing noticeably
So this does not disable all logging. It only blocks the noisiest TRACE level.
Guys, if on linux use https://github.com/graysky2/anything-sync-daemon
To put the entire folder on tmpfs (ram), this will completely absorb the churn, given you also tackle the size growth.
Oh, that's a good one. Can we replicate this on macOS 26 (Apple M chips)? @interfector18
Hasn't the error been fixed? (Windows Codex App)
You don’t want the entire folder on ramdisk.
Just the 3 SQLite files.
Just symlink the 3 files to /dev/shm/ on Linux
And on macOS do the same symlink after making a ramdisk with diskutil
Its all built in, no need to install anything else.
Can't Fable fix it ?
still not fixed on desktop app(windows and macOS)
Created a small macOS utility for the log guard and ramdisk fix https://github.com/bitbybob/codex-ssd-fix
Mainly for my different devices but perhaps it helps someone else ✌️
It will only symlink the 3 SQLite files to the ramdisk.
Note: For now you have to run it once per reboot but Im considering to add it to the startup directly.
All these workarounds/hacks are getting ridiculous. OpenAI should just patch the root cause and close this out permanently.
Honestly, my gut feeling is they're so overloaded that none of them are even watching this issue anymore and are aware this is still a problem. I don't know how else to explain it.
Prime example of overengineering :p
Just put that in a .sh :
Fair enough but this wont add the log guard + I wanted to have a simple CLI, so I can just toggle it whenever with easy to remember commands. As I said made it for me, just thought I share.
That said OpenAI will most likely just lessen the reliance on this sqlite dbs, but not get rid of them. Anyone with long running loops should seriously consider to ramdisk these anyways.
when 0.143.0 will be released? thanks
<img width="2546" height="960" alt="Image" src="https://github.com/user-attachments/assets/d14e43d1-030f-4c97-b3a5-43ac156db24b" />
Alreadt Fix it?
Linking for easier review:
And then from earlier:
I haven't looked deeper to see if #29599 was also backported to a
v0.142.xversion or not; or whether that is even relevant now that #30771 landed.I tested 0.142.5 and it was not fixed
@lock-down True.. :( Do you have any details / specifics on which parts are still an issue?
Refer to this https://github.com/openai/codex/issues/29532#issuecomment-4850466476
I tested 0.142.5 and it was not fixed+11111111111111
so is there an official or best work around, reading this thread just has 100 people all saying "do this, do that, this works, this won't work"... would be cool to just clearly know what band-aid to actually use...
Nothing official.
Apply the patch that you vibe more with; they both work.
If you think editing the sqlite triggers is best, do that.
If you think putting it in a ramdisk is best, do that.
I’d argue ramdisk is the safer ‘apply once and forget about it’ option as it ensures zero ssd writes even if codex updates and recreates the sqlite and it loses the sqlite hack.
can you please quote the ramdisk fix for me so i make sure i'm applying the right one
Unofficial Codex SQLite Workaround Summary
The consensus seems to be that everyone should apply the SQLite trigger in the next comment. It's the easiest workaround, blocking the noisy
TRACErows, while still allowingDEBUG,INFO,WARN, andERRORrows. This reduces what gets written, but it does not completely fix the logging behavior.The main downside is that it is not permanent if the database is replaced. Right now, Codex can rebuild
logs_2.sqliteif it is corrupt, and this workaround would not be included in the fresh database. Future versions could also change behavior in a way that requires re-applying it.So, advanced users who want extra SSD protection may want to also consider RAM-backed SQLite files in the third comment. That's not too difficult for macOS/Linux, but harder on Windows.
Recommended for Everyone: SQLite Workaround
EDIT: I'm a user just like you. This is "recommended for everyone" because it seems to be the user consensus as a good idea.
This blocks only
TRACErows in Codex's SQLite log database. It keepsDEBUG,INFO,WARN, andERRORrows.If you have
sqlite3installed, you can run the commands below. Otherwise, give Codex a link to these comments and ask it to apply the SQLite workaround. It should check your actuallogs_2.sqlitepath, install the trigger if missing, and run the WAL checkpoint.The SQL being applied is:
macOS / Linux with
sqlite3Windows PowerShell with
sqlite3Notes:
PRAGMA wal_checkpoint(TRUNCATE)is included to shrink the current WAL after installing the trigger.Advanced Add-On: RAM-Backed SQLite Files
This is a strong optional add-on, but I don't recommend it for most users. It protects your SSD only while Codex is actually writing the log database in RAM. If a recovery path or future update creates a fresh
logs_2.sqliteback on disk, the RAM setup would no longer be protecting you.I would still apply the SQLite workaround first. RAM-backed files reduce SSD writes by moving the database into memory, while the SQLite workaround reduces how much gets written to the database in the first place.
Honestly, if the notes below are not enough for you to know how to do it confidently, you might be better off only running the easier SQLite workaround. You could always point Codex here and have it help you implement this. There are not universal ready-to-run instructions here because it depends on your OS and how you want the RAM-backed storage to start across reboots.
The idea is to move the hot SQLite files off the SSD and into memory:
Important caveats:
logs_2.sqlite*files and creating fresh empty files in RAM. Moving a huge existing DB into RAM can consume a lot of memory, and using fresh files avoids needing toVACUUMit.General shape
~/.codex/logs_2.sqlite*files.logs_2.sqlite,logs_2.sqlite-wal, andlogs_2.sqlite-shmfiles there.~/.codex.Linux
Use a tmpfs-backed location such as
/dev/shm.Do not use
/tmpunless you know your system mounts/tmpin memory.macOS
Use a RAM disk, for example with
hdiutil.Example macOS sketch
This is not a polished installer, but one snippet shared in the thread was:
Windows
This is possible with third-party RAM disk software plus symlinks or junctions, but I would not recommend it as a general workaround. Use the SQLite workaround unless you already know how you want to manage a Windows RAM disk.
I would recommend a different approach for fixing this issue:
Excuse my ignorance but why is it logging at TRACE in the first place ?
That seems ridiculous
100%. Everything else talked about here are just workarounds since OpenAI hasn't addressed this since the commits they added that at least made it better.
There is no reason whatsoever to use TRACE for a production software release.
I have disabled
INSERTing into the log table as other users have suggested. You should do the same.When will be fixed?
At this rate, the notification emails from this thread are going to write as much to my SSD as Codex itself 😂
I dug into this a bit further since it's still causing significant SQLite growth on my machine even on the latest stable release.
Confirmed: PR #29599 ("Stop persisting bridged log events", merged 2026-06-23) fixes the single largest remaining noise source (
target == "log"bridged events), but it is not included in the current stable releaserust-v0.142.5(published 2026-07-01, 8 days after the PR merged).Evidence:
rust-v0.142.5'scodex-rs/state/src/log_db.rsonly has theopentelemetry_sdkDEBUG/TRACE guard inon_event— theif metadata.target() == "log" { return; }guard from #29599 is absent:https://github.com/openai/codex/blob/rust-v0.142.5/codex-rs/state/src/log_db.rs#L200-L216
rust-v0.143.0-alpha.36(published 2026-07-05):https://github.com/openai/codex/blob/rust-v0.143.0-alpha.36/codex-rs/state/src/log_db.rs#L200-L207
On my machine, a single ~104s session produced 1518 rows in
logs_2.sqlite: 1309 (86%) were TRACE, and 961 of those (73% of all TRACE rows) hadtarget == "log"exactly — precisely the events #29599 is meant to suppress.Looks like the
0.142.xrelease branch just didn't pick up this cherry-pick. Could a patch release (e.g.0.142.6) backport #29599 (and any other log-volume fixes merged since) so people on the stable channel actually benefit? Right now the only way to get this specific fix is the alpha channel.At this rate, all of us are paying monthly subscription fees to OpenAI to kill our SSDs for fun.
Here’s the local change I made to stop the excessive SQLite log writes:
This disables the SQLite tracing log sink in both the app server and TUI startup paths. It stops Codex from continuously writing tracing logs into
~/.codex/logs_2.sqlite, while leaving the other logging, feedback, and OpenTelemetry layers intact.Same problem
@jif-oai @anp-oai @pakrym-oai @rka-oai @bolinfest @etraut-openai @xl-openai @aibrahim-oai @cconger @sayan-oai @canvrno-oai @celia-oai @owenlin0 @richardopenai @tamird @charlesgong-openai @felixxia-oai @fcoury-oai @viyatb-oai @adaley-openai @apanasenko-oai @shijie-oai @iceweasel-oai @won-openai @guinness-oai @jameswt-oai @rhan-oai @wiltzius-openai @winston-openai @codex @ericning-o @stefanstokic-oai @abhinav-oai @alexsong-oai @dylan-hurd-oai @charliemarsh-oai @fjord-oai @mchen-oai @mzeng-openai @nornagon-openai @adrian-openai @fc-oai @marksteinbrick-oai @zanie-oai @ddr-oai @gpeal @rasmusrygaard @xli-oai
I want to connect a few related user-impact threads here because #28224 should not be closed as only a “large SQLite file” issue. This is a local resource-safety, privacy, and auditability problem.
The current mitigations reduce some hot paths, but the persistent SQLite log sink still appears to be deny-list based. In current
main/0.143.0-alpha,log_db::default_filter()still starts fromLevelFilter::TRACEand then excludes selected targets. That is fragile for a production Desktop/CLI app. The safe default should be low-volume by construction: WARN+ globally, INFO only for intentionally compact Codex-owned audit events, and TRACE only behind an explicit short-lived diagnostic mode.Stable users also need a clear answer. As of the latest stable I checked,
rust-v0.142.5, important follow-up behavior from #29599 was not present in stable even though it exists in alpha/main. Please publish the exact stable CLI version and Desktop build that fully contain the fix, and keep this issue open until that build is verified by aggregate-only disk/SQLite measurements.There is also a privacy angle: persistent TRACE logging can retain local paths, tool output, session details, and payload-like diagnostic content. Users should not need to inspect or post raw
feedback_log_bodyvalues to prove the bug. The official verification path should use aggregate metadata only: row-id deltas, retained row counts, level/target counts, WAL size/mtime, process bytes written, and checkpoint behavior.This also connects to the app-server/plugin usage-audit gap discussed in #31125 / #30918. Local persistence is currently too noisy for disk safety but still not structured enough for usage triage. A better design would persist compact audit records locally:
thread_id,turn_id, model, tool/plugin, timestamps, token counts, cache counts, billing/limit category, request byte sizes, and result/error summaries — without storing high-volume TRACE bodies in SQLite.Concrete asks:
Related context:
Please treat this as a product reliability issue, not a cosmetic logging issue. Users should not have to discover SSD wear through Activity Monitor, SMART counters, or SQLite forensics.
@agentHits I've come to the conclusion that no one from OpenAI is monitoring our comments on this issue anymore. I don't know how to explain this otherwise. I'm sure they wouldn't be reading all this and ignoring it. The only thing I can think of us more of us need to be tweeting to OpenAI employees and replying to Tibo's "what should Codex do next" tweets with "fix issue 28224 and stop destroying consumer SSDs!" This is an easy fix, and the delay since the few commits issued a while ago have cost consumers a lot more SSD endurance. Codex estimated to me low single digit to low tens of millions of dollars of damage to consumer SSDs from when the bug first happened until shortly after this issue was posted. This is ridiculous.
I think they're severely overburdened by new issues and simply can't keep up, and that several major issues like this, ridiculous CPU/GPU usage do to animations that can't be turned off which is chewing up probably millions of dollars in electricity, etc, just go by largely unnoticed. They should be able to run Codex loops that analyze what is causing the most customer pain, and I don't know why they aren't running that.
I mean, I'm running the workaround so it's not affecting me anymore, but it's really irritating that this bug ate up so much of my SSD endurance and that OpenAI isn't offering anything in return, let alone giving it another moment's thought.
What makes any of you think OpenAI staff/leadership cares about our SSDs? There are no incentives for them to care.
The only way to get this fixed is to make it loud. We need to tie this directly to their corporate narrative: OpenAI and Anthropic keep telling the world that AI is going to replace human workers, yet they can't even use their "god-like" models to fix a basic, clearly identified bug in their own code.
Instead of all these useless benchmarks ranking which model is "better," we need a meter to track the disastrous bugs they fail to fix. Let’s see a real-world benchmark: how many fully identified bugs can these "frontier models" actually resolve? Currently, not too many. That number should be the true measure of their capability.
Quick follow-up — 0.143.0 (published today) actually has #29599 in it now, and it works.
I upgraded and ran a session that ended up hitting 5 reconnect retries plus an HTTP 403. Out of 189 log rows total, only 2 were TRACE, and neither had target=="log".
Reading through the release notes; particularly the individual commits (since the summaries at the top are quite often VERY lacking), I also saw some other follow up fixes mentioned.
I forget the exact ordering of them; but these are the tabs I opened based on it + the earlier fixes it referred to + etc:
>
> This restores the low-volume per-request signal proposed in bk-nvidia#3 without bringing back per-WebSocket-event TRACE logging.
i have uninstalled it, not give up, but waiting the issue Completely resolved
So I'm wondering if the new CodeX desktop application released on July 10th, which merged the original ChatGPT and GPT Work, solved the problem of excessive log reading and writing to the SSD😰?
Actually, that’s not the case. After updating, I’ve noticed the new Codex app (or ChatGPT, as it’s called) is still writing to my SSD at dozens of MB per second. What can I say? 😅😅
Found some more useless writes;
~/Library/Application Support/Codex/sentry/scope_v3.json < 2.51 GB/day but it's just 128kb - constantly overwritten/pruned
~/.codex/models_cache.json < 1.05 GB/day but it's only 270 KB - constantly overwritten/pruned
Opened another ticket to track it though as it's not SQLite per se. https://github.com/openai/codex/issues/32496
Thanks for the bug reports. We think we've addressed the causes of the excessive log writes. I'm going to close this issue as fixed. If you are still seeing excessive writes, please open a new bug report and provide details.
Which version has it fixed? Is it in the desktop app?
Our series of fixes for this problem are in the latest shipping desktop app, CLI, and IDE extension.
Not quite yet. 0.144.1 does not have #31789, #31790, #31791, and #31792. 0.145.0-alpha.4 includes them, so 0.145.0 likely will too.
Also, please see #32496. A different root cause is causing about 1.3 TB/year in unnecessary writes, according to the numbers in the issue. (Much less than was on this issue.) Codex is continually rewriting
models_cache.jsonandscope_v3.json.Would it be possible for OpenAI to add a regression test that ensures: (1) Codex during idle doesn't make more than a very minimal amount of I/O; and (2) Codex during usage doesn't absurdly increase its I/O? It might be best to split 2, into one version that fakes the model to test the harness in isolation, and one end-to-end test that makes sure new model/harness combinations don't come up with something that bumps it significantly. The latter could of course trip from random model behavior. If OpenAI logged and compared the values, they would not only see spikes but also worrisome trends in I/O usage that could be investigated.
While at it, testing CPU and GPU usage similarly would be a big help. There are several issues about crazy high usage, often tracked down to animations being unnecessarily repeatedly updated a crazy number of times a second.
@etraut-openai Codex has been tracking this issue for me. I asked its opinion (GPT 5.6 Sol High), and it doesn't think this is fully solved:
---
I retested the SQLite logging behavior on macOS. The upstream fixes have substantially reduced the original churn, but the current desktop build still persists noisy TRACE/DEBUG activity at a much higher rate than when the local filter is enabled.
| Scenario | App/engine | Mitigation | Duration | MAX(id) change | Rate | Net retained rows |
| --- | --- | --- | ---: | ---: | ---: | ---: |
| Earlier affected build (July 1) | codex-cli 0.142.5 | Off | 96.9s | +3,212 | 33.1 IDs/s | +57 |
| Current desktop build (July 12) | App 26.707.51957, bundled codex-cli 0.144.0-alpha.4 | Off | 41.45s | +305 | 7.36 IDs/s | +9 |
| Same current build | App 26.707.51957, bundled codex-cli 0.144.0-alpha.4 | On | 41.89s | +19 | 0.45 IDs/s | +1 |
The mitigation is a local SQLite trigger that rejects TRACE/DEBUG records and known noisy targets. It does not block INFO, WARN, or ERROR logging.
This shows two things:
During the current-build test without mitigation, 305 IDs were allocated while only 9 additional rows remained. That is consistent with continuing insert-and-prune activity.
The newly retained records were dominated by:
No log bodies were read during these measurements.
Is this residual TRACE/DEBUG churn considered expected after the fixes? If not, is desktop app 26.707.51957 missing part of the fix, and which desktop or bundled CLI version should contain it?
@gustavopch It seems like you're still using
0.144.0-alpha.4in those tests; whereas an earlier comment from @darlingm suggests that there are more fixes that will land in0.145.0-alpha.4+, that sound like they should address some if not all of those:So are we getting some refunds/limit resets or ANY compensation for killing our SSDs? For weeks or nah?
@0xdevalias Ah, thanks for pointing it out. I just updated from
26.707.51957to26.707.61608and the bundled Codex CLI is still0.144.0-alpha.4. I guess we'll have to wait a few more days.So has this issue been fixed in the latest version of the Codex desktop app?