Codex Desktop becomes unusable on long active threads due to app-server/renderer memory and TRACE log churn
Summary
Codex Desktop becomes nearly unusable with long-running active threads, even after compaction-aware local transcript pruning.
The slowdown appears to come from the Codex app-server and renderer repeatedly handling large hot conversation state and logging large websocket/SSE response frames into logs_2.sqlite.
Environment
- Codex Desktop: 26.429.30905
- Electron: 41.2.0
- macOS: 26.0.1 (25A362)
- Machine memory: 16 GB
Observed behavior
During the slowdown:
codex app-serverspiked to ~64% CPU.codex app-serversampled physical footprint peaked at ~4.4 GB.- A Codex renderer reached ~1.07 GB RSS.
logs_2.sqlite/ WAL grew by about 1.4 MB in one second.- Recent log rows were dominated by TRACE entries from:
codex_api::endpoint::responses_websocketcodex_api::sse::responses- raw-ish response/frame logging such as
response.completed/ received websocket frames - One active long-running thread had grown back to ~839 MB with 22 compactions.
- The app remained sluggish even after pruning older pre-compaction rollout records, until restart/reload.
Chronicle was not the active CPU source in this case.
Why this seems like a Codex Desktop issue
Compaction-aware pruning helps reduce hot rollout JSONL size, but the running Desktop app still appears to keep or reconstruct very large hot thread state in app-server/renderer memory.
Separately, TRACE logging of large websocket/SSE frames can make logs_2.sqlite churn quickly, which seems to amplify the slowdown.
This makes long-running "main" threads effectively degrade over time, even when compactions exist and old raw history has been pruned locally.
Expected behavior
Long-running threads should remain usable after compaction. Codex Desktop should not need manual JSONL pruning, log rotation, or full restart to recover basic responsiveness.
Suggested fixes
- Truncate or disable large TRACE websocket/SSE payload logging in normal Desktop builds.
- Avoid retaining/rendering full hot thread state after compaction.
- Lazy-load old transcript/UI history instead of materializing the whole active thread.
- Add a first-class local "prune/compact UI history" action that preserves agent-visible compacted context.
- Release app-server/renderer in-memory thread state after compaction/pruning without requiring a full app restart.
- Add diagnostics that show which active thread/log source is causing app-server or renderer pressure.
Impact
For users who keep long-running main threads open, Codex Desktop can become almost unusable: high CPU, high renderer/app-server memory, heavy SQLite log churn, and severe UI lag.
10 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Someone investigated this in #21211 You can improve performance just by truncating titles to 120 chars in state_5.sqlite but the sidebar still loads the full first message just on launch so it's still problematic.
Adding another Windows Desktop data point that matches this issue.
Environment:
OpenAI.Codex_26.527.3686.0_x64__2p2nqsd0c76g0%USERPROFILE%\.codexObserved local DB state while the app was running:
logs_2.sqlite: ~812.9 MBlogs_2.sqlite-wal: grew to ~100 MB before checkpoint; after one successful checkpoint it dropped briefly, then grew back to ~75.7 MB during continued uselogsrows: ~180,537state_5.sqlite: ~4.36 MBlogs_2.sqlite: ~115,943 pages, about ~452.9 MB reclaimable/free pagesTop log targets by estimated bytes:
codex_api::endpoint::responses_websocket: ~101 MB / ~23k rowscodex_otel.log_only: ~33 MB / ~26k rowscodex_otel.trace_safe: ~29 MB / ~24k rowscodex_client::transport: ~24 MBExperiment:
PRAGMA wal_checkpoint(PASSIVE)followed byPRAGMA wal_checkpoint(TRUNCATE)onlogs_2.sqlitewhile Codex Desktop was open immediately reduced the perceived UI jank.This makes the issue feel like normal Desktop interaction is being affected by log DB/WAL growth and SQLite churn, not just long model latency. A built-in safe action such as "Optimize local data" / "Clear local diagnostic logs", plus automatic log rotation/checkpointing or bounded TRACE logging, would likely help users recover without manually touching SQLite files.
same issue
Another data point from Codex Desktop 0.140-alpha on Windows 11:
logs_2.sqlitereached 3.4 GB over 11 days (matches the ~10-day retention; rows pruned logically but no VACUUM, so disk stays allocated).responses_websocketalone ~1 GB), INFO 354 MB, DEBUG 57 MB. Consistent with #17320 (SQLite sink ignoringRUST_LOG).codex app-serverprocess kept the WAL open after the GUI was closed (related: #22444). Killing the orphans was required before the file could be moved..codex/skillsfile watcher fired continuously on__pycache__(.pyc temp files) and bundled-plugin cache churn — each event loggedskills cache cleared+ askills/changedapp-server event at TRACE, inflating the DB further.Mitigations that restored the app: kill orphan app-servers, move the oversized
logs_2.sqliteaside (app recreates an empty one), clear stray__pycache__. A config/env knob to cap or disable the SQLite TRACE sink would help a lot.Adding a fresh macOS data point from a current Desktop build. This looks like the same class of issue, but with both renderer CPU and app-server TRACE/log/MCP churn visible at the same time.
Environment
26.616.81150(CFBundleVersion4306)149.0.7827.115codex-cli 0.142.027.0 (26A5368g)on arm64/Applications/Codex.app/Contents/Resources/codex app-server --analytics-default-enabledObserved CPU
While the app was sluggish, repeated
pssamples showed:Earlier samples in the same run showed the renderer around
80-151% CPUand app-server around18-25% CPU.The renderer was the largest CPU consumer, but the app-server was also continuously active.
logs_2.sqlite churn
Local log DB state:
Short interval sample:
That is about
381 log inserts/sec, while the app was still running normally from the user's perspective.Recent log rows were dominated by TRACE/DEBUG/WARN entries like:
Top recent rows by target/body included repeated
session_loop{...}:submission_dispatch{...}entries undercodex_mcp::connection_managerandcodex_api::sse::responses.MCP process multiplication
At the same time, the app-server had multiple repeated direct child process groups. Sanitized count:
Most of these children were individually low CPU, but app-server was still spending CPU managing/logging the aggregate connection/event stream.
Samples
sampleon the renderer for 5 seconds:329.9M726.0Msampleon app-server for 5 seconds:267.7M278.2Mtokioworker threadssqlx-sqlite-worker-*sqlite3_stepsqlite3_wal_checkpoint_v2tracing_core::event::Event::dispatchcodex_state::log_db::MessageVisitorcodex_protocol::dynamic_tools::normalize_dynamic_tool_specstokio::fs::file::File::poll_readWhy this seems related
This looks like a combined feedback loop:
The external MCP children themselves were not the primary CPU source.
Expected behavior
Codex Desktop should not sustain
100%+renderer CPU plus30%app-server CPU while tool subprocesses are mostly idle. TRACE logging and MCP status/event streams should be bounded, filtered, batched, or deduplicated so that normal Desktop use does not continuously drive hundreds of SQLite log inserts per second.Related
This also overlaps with the SQLite TRACE churn tracked in #28224 and related follow-ups, but the user-visible symptom here is Desktop CPU/UI pressure with renderer + app-server both hot on
26.616.81150.I can reproduce what appears to be the same issue on Windows, and I isolated
logs_2.sqliteas the trigger with a local A/B test.Environment
OpenAI.Codex_26.707.3748.0_x64codex-cli 0.140.022631.5768, x64Symptoms
Creating a new task, switching tasks, or opening a history item that had not yet been opened would freeze the Codex UI for several seconds. During the worst reproductions, the stall also made the rest of the Windows desktop feel temporarily unresponsive. Restarting Codex or rebooting Windows did not resolve it.
I also tested disabling Browser/Chrome integrations, plugins/MCP servers, Figma, and
node_repl, and tested with a clean Electron UI profile. Those changes did not resolve the stall. Moving most session history was also not the decisive factor.Isolated result
The local diagnostic log database had grown to:
logs_2.sqlite: 220.23 MBlogs_2.sqlite-wal: approximately 5.63 MB at the captured pointAfter moving the 220 MB
logs_2.sqliteout ofCODEX_HOMEand allowing Codex to create a fresh log database, the task/window switching stalls disappeared immediately. Restoring normal Codex features did not bring the stalls back.This is notable because the problem occurred at roughly 220 MB, substantially below the ~813 MB database reported in the original issue. It suggests the trigger may depend on fragmentation, row count, checkpoint behavior, or local SQLite contention rather than file size alone.
Temporary workaround that worked locally
logs_2.sqlite*files fromCODEX_HOME(%USERPROFILE%\.codexby default).This did not remove conversation/session history in my test. I am not attaching the original SQLite database because diagnostic logs may contain private local paths, commands, or task data.
A built-in Clear/Rotate diagnostic logs or Optimize local data action, plus bounded retention and automatic WAL checkpoint/VACUUM behavior, would prevent users from needing to manipulate SQLite files manually.
I’m seeing a closely matching slowdown on Codex Desktop for macOS and collected read-only local diagnostics.
Environment:
26.707.91948(build5440)0.144.426.5.2(Apple Silicon)Observed while the UI felt sluggish:
sample: ~955 MB, with a recorded peak of ~3.3 GBcodex app-serverRSS: ~487 MBLocal Codex state:
~/.codex/sessions: 7.3 GB / 829 files~/.codex/archived_sessions: 3.7 GB / 449 files~/.codex/logs_2.sqlite: 1.7 GBcodex_mcp::connection_manager: ~102 MBcodex_api::sse::responses: ~82 MBcodex_core::stream_events_utils: ~51 MBImportant caveat: during a five-second idle sample, the SQLite DB/WAL did not grow and renderer CPU later settled around 1–2%. So I cannot confirm continuous write churn or a permanent CPU spin. The strongest local signal is accumulated hot thread/rendering state plus V8 GC pressure, with the large log DB potentially amplifying it.
The app had updated to this build earlier the same day, but I do not yet have an older-build control test. No local data was deleted or modified during diagnosis.
Follow-up after a full Codex Desktop restart: the UI remained very slow, so restart is not an effective workaround in this environment.
Fresh-process evidence roughly eight minutes after relaunch:
v8impl::Reference::InvokeFinalizerFromGC.codex app-serverbriefly reached ~21% CPU and ~550 MB RSS, although a later sample mostly found its Tokio workers waiting rather than a continuously hot loop.rmcp::service; other leading sources were MCP connection management and app-server outgoing-message TRACE logs.The desktop startup log also emitted repeated:
ResizeObserver loop completed with undelivered notificationsIAB_LIFECYCLE route window is not liveIAB_LIFECYCLE browser use route window missing for cursor/active stateThose Browser Use warnings referenced many existing and client-new-thread conversation IDs during startup reconciliation. They appear related to the IAB route-management issue family (for example #20678), but I cannot prove they are the primary cause of the UI lag. My current read is that they may amplify the long-thread/state-replay problem described here.
System pressure remained low: zero swap and generally high CPU idle. This makes a persistent Desktop build/state-reconciliation issue more likely than machine-wide resource pressure.
Adding a fresh Windows Desktop reproduction from the current app build. This appears to match this issue and the symptoms reported in #19923 and #20544.
Environment
26.707.12708.010.0.26200(build 26200)31.0.21925.1001(2026-05-20)32.0.16.1074(2026-02-07)Reproduction and symptoms
Privacy-safe local measurements
During a 35-second sample while opening an affected thread:
ChatGPT.exeprocess working set grew from about 356 MB to 1,784 MB.Examples of short but internally heavy local histories:
Troubleshooting already performed
The behavior remained unchanged after all of the above. The transient growth and later release of the main-process working set make this look like expensive thread-state materialization/deserialization or GC on the UI-critical path rather than a GPU-driver or machine-capacity problem.
Expected behavior: old tool outputs and image/screenshot records should be lazily hydrated or virtualized so that switching threads does not block pointer and keyboard input.
I can provide sanitized per-process samples or collect a specific performance trace if maintainers indicate which artifact would be most useful.