app-server: WebSocket notification fan-out serializes once per recipient

Open
#36,691 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Refactor
Clarity
Mostly clear
Activity status
Quiet
Tech stack
rust

Research direction

Start with send_server_notification_to_connections in codex-rs/app-server/src/outgoing_message.rs, then trace route_outgoing_envelope and filter_outgoing_message_for_connection in codex-rs/app-server/src/transport.rs. Read run_websocket_outbound_loop and serialize_outgoing_message in the transport crate, and coordinate with #36655. Done means admitted unchanged notifications share serialization while per-connection queues, filtering, failures, ordering, and framing remain unchanged.

Written by the indexing model from the issue text.

Description

app-server enhancement performance
What variant of Codex are you using?

App Server

What feature would you like to see?

I found a potential performance concern in current source rather than a confirmed user-visible bug. When the same ServerNotificationEnvelope is admitted for multiple WebSocket recipients, route_outgoing_envelope clones the typed OutgoingMessage into each bounded writer queue. Each run_websocket_outbound_loop then calls serialize_outgoing_message independently, so identical eligible notification payloads are serialized once per WebSocket recipient.

Please consider a shared immutable notification wrapper with one lazily initialized serialized JSON string. Reuse it only after should_skip_notification_for_connection admits a recipient and filter_outgoing_message_for_connection leaves the notification unchanged. Per-connection queue entries and write_complete_tx values must remain separate; serialization-failure handling, FIFO delivery, bounded slow-client disconnect behavior, targeting, initialization checks, opt-outs, experimental gating, and WebSocket text framing must remain unchanged. Requests, responses, and any payload rewritten per connection are outside this proposal.

Additional information

Evidence

  • send_server_notification_to_connections builds one targeted notification and clones it for selected connections.
  • route_outgoing_envelope identifies eligible broadcast connections and clones the same message per recipient.
  • filter_outgoing_message_for_connection only rewrites command-execution approval requests. For notifications, should_skip_notification_for_connection can drop a recipient but does not rewrite the delivered payload.
  • run_websocket_outbound_loop calls serialize_outgoing_message after dequeueing each message, creating a separate JSON string per recipient writer.
  • Related but distinct: #36655 tracks the targeted emitter’s unnecessary deep payload clone, while this report concerns repeated downstream WebSocket serialization. A shared notification wrapper or cache may address both costs, so implementation should be coordinated with #36655 rather than introduce a parallel notification representation. #34761 removed an intermediate JSON Value conversion but still serializes each queued WebSocket copy.

Impact

Not measured. An identical admitted notification may be serialized and allocated once per WebSocket recipient. Potential CPU and allocation cost scales with notification size, eligible WebSocket recipient count, and notification rate; throughput, latency, allocation volume, and occurrence have not been measured.

Question

Would maintainers consider a shared lazily serialized notification wrapper that preserves per-connection filtering, queues, write-complete signaling, and WebSocket framing?

I checked all relevant issues, comments, pull requests, discussions, and release notes; this report is not a duplicate.

I am reporting this finding only and am not proposing a pull request unless a maintainer invites one.

Disclosure

Investigated thoroughly with GPT-5.6 (high reasoning effort), using Oh My Pi as the agent framework.

This report is not generic or unreviewed AI-generated output. Its claims were checked against the cited evidence, and it includes the relevant detail intended to help maintainers resolve the issue.

If reports like this are not useful to the project, please let me know and I will refrain from submitting similar ones. My intent is to help without wasting maintainer time or energy or discouraging their work.

Thank you for your work.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.