Remix loader deadline: passive request.signal abort vs manual Promise.race timeout
0 reputation · 10 Apr 2025, 03:18 UTC
Goal: enforce a server-side deadline for long-running Remix loaders while responding correctly when a client aborts a navigation fetch.
Remix passes the incoming Request to server loaders, and request.signal is an AbortSignal that flips to aborted when the browser cancels the request. Remix has no built-in declarative loader timeout, so a deadline must be added manually, typically by racing the loader against a setTimeout-driven AbortController or Promise.race. The signal only reports cancellation; it does not interrupt database queries, native fetch calls, or promises already in flight, and the server may finish the work and discard the result. defer() and Await stream resolved values but add no abort or timeout semantics.
Version assumption: Remix v2, because request.signal availability and loader argument shape can differ between releases and deployment targets.
- Should a long-running loader treat
request.signal.abortedas sufficient to stop side effects, or is a manual timeout required to reject the loader promise? - When the manual deadline fires first, should the loader reject or return an error response, and what happens to client error boundaries?
- Can the underlying server work continue after either abort or timeout, creating duplicate side effects?