Jakub Holý: how to build a shopping cart

(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.


However there are other concerns than simplicity and time-to-production that we could have been taken into account, I believe. But I failed to communicate those in time. The current solution would have been perfect if the network transfer times were negligible and if the backend service was 100% reliable. None of that is true. Every call takes at least 300ms and the backend can be overloaded or (as yesterday) unavailable due to network issues. I there is a high load, all customers will experience a very slow cart multiple times.

I prefer to design for robustness, with a healthy does of paranoia with respect to performance and the availability of any dependencies. I would have advocated to create the shopping cart in-browser and to hold the state primarily there, using localStorage (if available) for persistence and sharing across pages and tabs, sending the content to the backend asynchronously. When the user clicks “buy”, the item would be added immediately to the cart, not after few 100s of ms or a few seconds. And if the backend eventually rejected the change, we would notify the user and remove it from the cart (an “optimistic transaction” – that is what Om Next does by default). If the backend is down, we can inform the user that fulfilling the order isn’t possible at the moment but that the browser remembers it (even if quit) and that they should come back and try later again. I would primarily talk to the backend only at the last possible moment, when the user clicks “go to checkout” – or, perhaps, if the backend isn’t overloaded, also after any change to the cart but asynchronously, to improve the perceived performance when the final button is clicked. The front-end and especially the browser code would be more complex and take longer to develop and test but it would be very well isolated from backend problems and would generate minimal load on the backend. I believe that in this case, it would be worth it. (Though I admittedly tend to overcomplicate things, with my performance and availability paranoia.)

He later writes they were able to improve the performance of the backend, which resolved some of the urgency of the issue.

I can agree with the need to resend failed requests from the frontend, but otherwise much can be kept on the backend? For sure, frontends are complicated. Maintaining state in two places is a permanent source of pain.

Post external references

  1. 1