Hot Path vs Warm Path
Hot path vs warm path
A hot path is work the user is waiting on right now. A warm path is work the system does speculatively so a later hot path feels instant.
The bug is treating them as the same kind of work. They may use the same store, provider, cache, and runtime, but they do not deserve the same priority.
The rule
Hot work gets first claim on scheduler time, IPC handlers, provider budget, locks, and stateful actors. Warm work gets bounded capacity and must be willing to lose.
That sounds harsh until you remember what warm work is for. It exists to improve the user's next action. If it makes the current action slower, it has betrayed its job.
Design shape
- Give warm work its own queue, lane, or priority class.
- Bound the queue and the number of in-flight jobs.
- Make stale work cheap to abandon.
- Keep each warm unit small enough that hot work can cut in quickly.
- Trace warm work separately from hot work so latency problems do not blur together.
Separate lanes are not enough by themselves. If both lanes immediately converge on one long-running lock or actor, the hot path still waits. See Priority Lanes Need Downstream Isolation.
Hot reads are the sharpest version of this. If an earlier phase promised to preload data, the read handler should not secretly repair that data through a slower path while the user waits. See Hot Reads Should Not Repair Cold State.
Spotuify example
In Spotuify, play/queue/search commands are hot. Queue warming is warm: after tracks enter the queue, the daemon can prefetch metadata, index records, cover art, lyrics, and embedded-player preload state before playback reaches them.
The important part is the boundary. Warming should not go through the same blocking path that handles the user's play/pause/next command. It should run in small batches, dedupe recent work, and let newer queue snapshots supersede older ones.
The 2026-06-02 player fix sharpened this again. Optimistic playback state made
the TUI feel quicker, but audio still kept playing when the actual transport
command waited behind slower work. Playback controls are hot all the way down:
state, event emission, player actor, and the local transport side effect. See
Optimistic UI Is Not the Side Effect.
The 2026-06-02 startup-seed fix sharpened the rule. Opening the TUI felt
harmless, but it was enough live-ish provider work to put the first play command
behind Spotify rate limiting. Startup hydration is warm work too. Seed from
cached daemon truth; do not spend provider budget merely because a client opened.
Mxr example
In Mxr, thread summarization sits in an awkward middle. The result is user-visible, but the LLM call is too slow and variable to live on the reader's hot path.
The code truth as of 2026-05-28: sync no longer backfills summaries in bulk. Opening an uncached thread can lazily start a debounced background summary, and pressing y starts one immediately. Both paths use daemon IPC instead of local TUI work, and the TUI renders a visible Summary block above the message while the request is running.
That makes it warm work with a visible result. It may start because the user landed on a thread, but it is not allowed to make scrolling, body loading, or mail actions wait.
The 2026-06-09 sync/mutation fix sharpened a different edge. Background sync is
warm from the user's point of view, but it touches the same provider account as
an archive or mark-read mutation. The answer was not to let them race. It was
to serialize provider work per account, add timeouts, and keep unrelated
accounts out of the wait. See Provider Lanes Need Account Scope.
See also
- Background Work Should Be Bounded and Supersedable
- Priority Lanes Need Downstream Isolation
- Nonblocking Work Needs a Visible Home
- Preload Belongs to the Resource Owner
- Warm Reusable Truth, Not Screens
- Hot Reads Should Not Repair Cold State
- Optimistic UI Is Not the Side Effect
- Provider Lanes Need Account Scope