Remix's Concurrent Submissions Are Fundamentally Flawed
Based on The PrimeTime's video on YouTube. If you like this content, support the original creators by watching, liking and subscribing to their content.
Remix’s “submission and revalidation” can still commit stale data to the UI when multiple mutations overlap and revalidations read/finish out of order.
Briefing
Remix’s “concurrent submissions” and its related “submission and revalidation” safeguards are portrayed as unreliable for real-world apps, especially when multiple mutations overlap. The core claim is that even with mechanisms meant to prevent stale UI updates, race conditions can still surface—leading to UI flicker, “deleted” items reappearing, or users seeing state that doesn’t match what the server ultimately committed.
The argument starts with a broader design debate: where application state should live—client or server. Client-side state can improve perceived responsiveness and enable rich interactivity, but it also risks divergence when server truth arrives late. Server-side state can reduce divergence, yet it still requires careful handling of latency and ordering. The discussion frames “offline support” as a weak justification for client-heavy state in typical websites, while latency and interactivity are treated as solvable even with server-driven approaches.
From there, attention narrows to Remix’s specific concurrency model. “Submission and revalidation” is described as a two-step pattern: after a mutation (like a form post that triggers a patch/delete), the client issues a follow-up request to reload data. That already costs extra round trips. More importantly, the concurrency promise—avoiding stale commits when overlapping actions occur—is challenged with concrete timing diagrams. The critique hinges on an incorrect assumption: that the revalidation that finishes first corresponds to the “earlier” or “correct” version of data. In overlapping requests, revalidation can read from the database at different moments, so an earlier revalidation may commit later to the UI, effectively rolling the interface backward in time.
A practical example makes the failure mode tangible: deleting multiple rows quickly can cause the UI to temporarily remove all rows, then “bring back” a row due to an out-of-order revalidation read, and later correct itself. The same pattern generalizes to non-trivial mutations where one action affects many properties—tracking what should be visible becomes difficult, and the UI can oscillate between states.
The discussion then explores why “just wait to revalidate until all submissions finish” is not a free fix. Doing so would require grouping actions that “collide,” stalling updates until the last one completes, and still not guaranteeing correctness when concurrent submissions modify overlapping resources—particularly in horizontally scaled or serverless setups where requests may hit different instances, experience cold starts, or encounter garbage-collection pauses.
Alternative solutions are offered as conceptually stronger but operationally complex: causal ordering (ensuring later operations depend on earlier ones), database-level serialization/locking (with performance and deadlock risks), sticky sessions plus ordering logic, or persistence via Phoenix LiveView-style long-lived connections where events are processed in order. The conclusion is that concurrent submissions driven by server state can become a source of race conditions and inconsistencies, and that addressing it robustly requires ordering guarantees or persistence—not just best-effort cancellation or timestamps.
Finally, the critique extends to Remix’s cancellation behavior: canceling a submission may not prevent the server from processing it if the request already crossed proxies/load balancers and entered the event loop, or if infrastructure timing differs. The result can be stale UI immediately after an action, potentially escalating from cosmetic glitches to user-impacting errors (e.g., a “Buy now” button reflecting fewer line items than what the server actually stored).
Cornell Notes
The central issue is that Remix’s concurrency approach—especially “submission and revalidation”—cannot reliably prevent stale UI updates when multiple mutations overlap. The pattern uses a second request to reload data after a mutation, but overlapping revalidations can read from the database at different times and commit results out of order. That can make the interface roll backward (e.g., deleted items reappearing) until later requests correct it. The critique argues that robust fixes require stronger ordering guarantees (causal ordering, sticky-session ordering, database serialization/locking, or persistent connections like Phoenix LiveView), not just best-effort cancellation or timestamps. The stakes range from flicker to potentially incorrect user decisions if the UI diverges from what the server committed.
What is “submission and revalidation,” and why does it create a correctness problem under concurrency?
Why is the “first revalidation finishes = correct version” assumption considered wrong?
How does the deletion example illustrate the race condition?
Why doesn’t “just revalidate after all submissions complete” solve everything?
What ordering/persistence approaches are proposed as more reliable alternatives?
Review Questions
- In overlapping submissions, what specific mismatch between “revalidation completion order” and “database read time” can cause the UI to revert to an older state?
- What additional guarantees are required to make causal ordering feasible in a horizontally scaled environment, and why do sticky sessions matter?
- Compare the trade-offs between database locking/serialization and persistent event ordering (e.g., Phoenix LiveView) for preventing stale UI after concurrent mutations.
Key Points
- 1
Remix’s “submission and revalidation” can still commit stale data to the UI when multiple mutations overlap and revalidations read/finish out of order.
- 2
The critique targets an incorrect expectation that the earliest revalidation completion corresponds to the correct (latest) database state.
- 3
Concurrent deletes can produce visible UI rollback, such as deleted rows reappearing until later requests correct the interface.
- 4
Deferring revalidation until all overlapping submissions finish requires collision grouping and can degrade UX by stalling updates.
- 5
In serverless or horizontally scaled deployments, requests may hit different instances, experience cold starts or GC pauses, and lose any implicit ordering guarantees.
- 6
Cancellation doesn’t necessarily prevent server-side effects if the request already progressed through proxies/load balancers and the event loop.
- 7
More robust fixes rely on ordering guarantees (causal ordering, sticky-session ordering, database serialization/locking, or persistent connections like Phoenix LiveView), not just best-effort client/server synchronization.