I wasn't looking for a performance problem. I wanted to see what happened when the network got slow enough that assumptions I normally never notice...
For further actions, you may consider blocking this person and/or reporting abuse
Any screen that fires a request per keystroke has that race, and wifi hides it because responses come back in roughly the order you sent them. Good one to lead with.
The other thing throttling cannot give you is a slow CPU. I found my worst screen by opening the app on a real mid range phone, and it turned out to be the one I was most proud of.
Yeah, Eusebiu, that's the honest version of it. Any screen firing a request per keystroke can have that race sitting there. WiFi just happens to keep the timing close enough that you rarely see it.
The CPU point is a good one, and it's not something network throttling touches. DevTools can slow the network, but it doesn't reproduce what happens when the same JS work is running on a mid-range phone. A screen can look completely fine on my machine while the real bottleneck is work happening on the main thread. I haven't tested this on a real device yet, so that's a pretty useful gap you've pointed out.
Good debugging post as usual! 😄 API order and timing control are some of the hard parts of using APIs. Nice point!
Thank you so much! 😊 Yeah, API timing is one of those things that can look completely fine until you hit the right conditions to expose it. That's exactly what happened here. Really glad you liked the post!
Here's a wild thought - just use an AbortSignal on your fetch and then cancel it when calling your
searchmethod instead of this insane "lastId" systemThanks Momchil.
AbortControlleris definitely an option here. I considered it, but the point of the example was specifically to handle out-of-order responses, so I used the request ID to make that check explicit. Even if the earlier operation continues, its result still can't overwrite the latest one.The biggest lesson is that timing is not truth. A timeout does not mean something failed, and a response arriving later does not mean it represents the latest state.
Reliable systems need to track state explicitly instead of making assumptions based on timing.
Exactly, Vinny. That's the core of it. The search bug was a stale response landing after a newer one; the autosave bug was a timeout getting treated as a failed save when it hadn't failed at all. The network exposed the timing window, but the underlying problems were in my application's assumptions about timing and state.
Shubhra, this is such a good reminder that things can look perfectly fine on our own setup and still break somewhere else 😅 I liked the 3G test idea, especially how it exposed bugs that the tests never caught.
Thank you, Hema! 😊 That was exactly what I was hoping to uncover with the 3G test. Things looked fine on my usual setup, but slowing the connection down made those hidden assumptions much easier to spot.
Great experiment and learning.
Yes, DevTools catching these bugs maybe standard. On localhost, near-zero latency hides missing cancellation logic because requests finish sequentially. Throttling adds latency, allowing out-of-order responses to surface when users interact mid-request.
Have you tested with 3G traffic experience at lower layers? Your hardware and operating system, maybe even browser could be able to handle this and your app may not even face some of the scenarios. Just curious, I did network level tests for some apps maybe 2 decades ago and things I was discovering with app level simulations never occurred when I pushed the slowness simulation at network driver level as the network and OS handled many of the issues and my app then was surfacing the issues that it needed to handle. In other words I discovered the exact issues that app had to deal with and not others that network and OS would handle for me. I was on windows btw, and this was 2 decades ago.
Just curious, if this is an option
Good question. For this experiment, I used Chrome DevTools to throttle the network and deliberately tested how the application behaved when requests took longer to complete. That was enough to expose the two application-level issues I was looking for.
I haven't tested the same scenarios by introducing the network conditions at the network-driver level, so I can't say how the results would compare there. Your point about separating what the OS/network stack handles from what the application itself needs to handle is a useful distinction.
In this case, the two issues I found were still application-level problems: the search UI accepted an older response after a newer one had already been requested, and the autosave treated a client-side timeout as a failed save even though the server could still complete it.
I'd be interested to try the lower-level approach as a follow-up and see what changes. Thanks again, Debashish, for taking the time to read the post and share your experience. I really appreciate it.
Thanks for sharing, very insightful article!
Thank you, Cathy! I really appreciate you taking the time to read it and share this. Glad you found it useful!
Nice write-up shubhra!! :D
Thank you so much, Divya! 😊 Really glad you liked it!