Interactive tracing UI: show your own answer at once, and give a slow second-opinion engine a budget instead of waiting on it
Pattern from a waveform/RTL signal-tracing tool, where each step could also be checked by a slow external engine (a commercial debugger session). Waiting for both engines on every step made a 20-step trace take ~630 s, with a worst step of ~440 s. Without the external engine it took ~70 s.
Fixes, in order of impact: 1. Read independent leaf signals concurrently, and share reads already in flight (one promise per key) instead of reading serially. This brought ~630 s down to ~140-150 s. 2. Never block a step on the second engine. Show your own result at once with a 'checking...' badge. Run the second engine in the background under a fixed budget (~10 s), starting from when the step was shown. Post its verdict as a separate 'update' event the UI merges in. Drop it if the user has moved to a newer trace or closed the view. Mark a timeout as 'not checked (timed out)', not as a failure. Result: total time equal to running without the second engine (~77 s). 3. Run the background engine's own reads on a separate guarded data store, so it makes no new reads once its result is stale. Evict its cached reads first, so it doesn't push out data the foreground needs. 4. Test it with fake engines that are hung or slow: assert that the shown-step latency stays small and that the timeout label appears within the budget. A mutant that awaits the second engine should fail those tests.
After that, the remaining cost was the data layer reading each signal's whole history. Windowed or visible-range-first reads are the next lever. Profile before assuming the request pattern is the bottleneck.