Skip to content

app-server: feedback log sqlite (logs_N.sqlite) grows unbounded — ~0.75 GB/day, no retention/rotation #26374

Description

@2vanm

Summary

The app-server's internal feedback/telemetry log database ($CODEX_HOME/logs_<N>.sqlite) grows without bound — no retention, no rotation, no size cap. On a long-running headless deployment (app-server driven 24/7) it reached 9.8 GB in ~10 days (~0.75 GB/day) before we noticed and manually cleared it.

This is distinct from state_<N>.sqlite (actual thread/session state), which stays small and healthy (~106 MB).

Environment

  • codex-cli 0.132.0 (codex app-server --listen stdio://)
  • Linux x86_64 (musl vendor build), driven continuously by an automation host (frequent short sessions: heartbeats, scheduled jobs, chat).
  • CODEX_HOME set to a persistent dir.

Evidence

logs_<N>.sqlite has a single dominant table logs:

1,420,123 rows, ~9.4 GB used (10.47 GB file, 1.08 GB freelist)
schema: id, ts, ts_nanos, level, target, feedback_log_body, module_path, file, line, thread_id, process_uuid, estimated_bytes

Bytes by column — feedback_log_body dominates at 7.3 GB. By target:

 5.88 GB  n=314,237  codex_api::endpoint::responses_websocket   (TRACE)
 0.44 GB  n=329,301  codex_otel.log_only
 0.39 GB  n=324,112  codex_otel.trace_safe
 0.21 GB  n=215,142  codex_api::sse::responses
 0.21 GB  n=    453  codex_core::client

Level mix: 675,801 INFO + 614,236 TRACE + 73,883 WARN + 23,110 DEBUG + 7 ERROR.

The largest single rows are ~800 KB each — full op.dispatch.compact / op.dispatch.user_input_with_turn_context request/response payloads serialised verbatim into feedback_log_body.

Steady-state growth (one row of the per-day breakdown):

2026-05-26  140,239 rows  0.71 GB
2026-05-27  136,379 rows  0.72 GB
...
2026-06-03  139,209 rows  0.75 GB

The logs_<N> suffix appears to be a schema version, not a size-based rotation — within a version the table grows indefinitely. RUST_LOG does not appear to gate these sqlite writes (no EnvFilter hook found for the feedback-log layer), and the only "bounded" reference in the binary (bounded_feedback_logs AS (...)) is a read-side CTE used when assembling a feedback bundle, not a write-side cap.

Impact

  • ~0.75 GB/day ≈ 22 GB/month, ~270 GB/year of pure telemetry on disk for any long-lived app-server deployment.
  • Full prompt/response payloads (including large compaction turns) are persisted indefinitely on the local disk — also a data-retention concern.

Expected behaviour

The feedback log should be bounded by default — e.g. a max age and/or max size with automatic pruning/rotation (à la a rolling window), or an explicit CODEX_HOME/config setting to cap or disable it. Ideally TRACE-level full-payload dumps should not be persisted to the on-disk feedback DB by default.

Workaround

logs_<N>.sqlite* is safe to delete while the app-server is stopped — it is recreated empty on next start and only debug/feedback-bundle history is lost. But this requires manual intervention and downtime since the file is held open continuously.

Metadata

Metadata

Assignees

No one assigned

    Labels

    CLIIssues related to the Codex CLIapp-serverIssues involving app server protocol or interfacesbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions