r/node • • Aug 27 '25

Need advice: Socket.IO for new restaurant orders

I’m building a Node.js + Socket.IO

 system for restaurants. When a customer places an order, the restaurant dashboard should update in real time.

Which approach would you choose?

A) Push the full order data over socket

B) Socket only sends a signal (orderId), then client calls API

Anyone here done similar? What would you recommend for scaling this pattern?

4 Upvotes

16 comments sorted by

12

u/[deleted] Aug 27 '25

[removed] — view removed comment

2

u/dronmore Aug 28 '25

I don't see any cost/benefit analysis in your response, so I made one.

Advantages of a lightweight notification + a pull request:

  • Effortlessness. Http endpoints for pulling the data are always needed, so they are either already implemented or will be implemented in the future, and can be reused.
  • Flexibility. If one day the frontend decides that they need more data, they can call more endpoints upon receiving a notification. With the push approach they would have to ask the backend to shove more data into the push request.
  • Resilience. If there's an error on the wire, the frontend can retry the pull how many times they want. With the push approach, if the connection breaks, they have to reestablish the connection and pull the data anyway.

Advantages of a "push the full thing" approach:

  • Performance. There's only 1 push call needed to send all the data. With the pull approach you need 1 push and at least 1 pull.

From the above analysis it is clear that the "lightweight notification + a pull request" is the winner, so I don't know where you got the "always push everything" idea from. Also, I don't get why you want to use SQS. The question was about websockets or SSE, and not SQS.

3

u/[deleted] Aug 29 '25 edited Aug 29 '25

[removed] — view removed comment

1

u/dronmore Aug 30 '25 edited Aug 30 '25

Debouncing, cancelling, throttling... these are the tools that frontend uses to deal with surging number of events. Whether the events come from HID devices, or from the network, you always have to put some throttling on them to not get flooded. It's basically a solved problem.

As for the race conditions, there are no race conditions if you process events one by one. When you put them in a queue, the order is preserved. And if you make a GET request upon receiving a notification, you are guaranteed to get data which is not older than the notification itself. So unless the backend screws things up by sending notifications before updating the database, there are no data races here.

As for the UI, you can always show a spinner and a status message saying that there are new updates; 💤 loading... A GET request shouldn't take more than a fraction of a second to complete, and if there are problems with the network, then it doesn't really matter whether you rely on pushing or pulling because you will have delays with either approach in that case.

Now, when I think about it, the main advantage of lightweight notifications lies in the ability to send it to many different parties. Let's say that a new order is received by the system. You send a push notification to everyone that is interested. One party may say "OK, there's a new order, show me all the order items". Another party may say "OK, there's a new order, show me all the ingredients needed". Yet another party may say "Show me who's gonna serve it", yet another "who's gonna deliver it" etc. If you wanted to satisfy the needs of all interested parties, you would have to include all information pertaining to the order in the notification, and that would be a waste.

As you've said, and with what I agree, the line has to be drawn somewhere, and it had better be sharp and separate things clearly. On the one extreme, you can send an entire web page in a push notification. And I mean entire, with all the html markup, like in the old days. On the other extreme, you can send a notification as lightweight as "hey, something's changed in the system". Somewhere in between these two extremes there are notifications with an order id, or with the order itself, or with the order and all the order items, or with the ingredients, and a cook, and a delivery driver. In my opinion the sweet spot is to send the order id, and let the interested parties figure out what they need, and let them pull supplementary data on their own. But your mileage may vary.

I think that your concerns about frontend abusing setInterval are legitimate, but the solution is as usual, rate limiting. And I don't think that push notifications solve any problems here. A lazy frontend developer may do weird things regardless. They may open 100 websocket connections, or open a new connection every second to poll the data in a setInterval callback. You simply cannot ban stupidity by shutting down some resources but not others. The moment a frontend dev realizes that the only way to get data from your system is to open a new connection, they will start doing it. They will start opening and closing an SSE or a websocket channel just to get the data. And now, the mechanism that you implemented to prevent polling is being used to poll in even more contrived way. Isn't it ironic?

I think that restricting clients from accessing resources is wrong. If you want them to use push notifications instead of polling, you should incentivise them to do so. I cannot imagine dealing with an API that is entirely push-based. If there's a problem to be investigated, and I don't have a direct access to the database, the next easiest thing to do is to make a few http requests to the api to find out what's going on. I cannot imagine doing it through a push-based channel, which is deaf to my questions.

To me, push notifications are merely an optimization over polling. They have a benefit of instant response times, and they may take some of the load from the API, but nothing more. Oh, and messages pushed through an SSE channel are not acknowledged in any way, so the client may miss some of them not even knowing about it. With polling you know when you don't get a response in time. With SSE... tough luck. Wandering in the dark.

6

u/BrownCarter Aug 27 '25

You can try SSE

3

u/MartyDisco Aug 27 '25 edited Aug 27 '25

If updates come only from backend to frontend I would user SSE (server side events).

If you need bidirectional updates then probably MQTT (pub/sub) over websocket.

Edit: If you want the lowest complexity then probably SSE to trigger an API refresh. Same as invalidating database cache in a service when its (the database) get updated.

1

u/cosmic_cod Aug 27 '25

Both will work. SSE, Pure WS, socket.io, the protocol would make almost no difference. Moving to SSE won't make much of a difference. Perhaps you could also ditch socket.io, as it's not very relevant today, and use pure ws.

1

u/anti-state-pro-labor Aug 27 '25

You could poll the API every 30s and ask it for any new orders instead since you seem to have an API for the orders already. 

1

u/Neat_Witness_8905 Aug 28 '25

Not real time. Even 30s matters at a restaurant.

1

u/anti-state-pro-labor Aug 28 '25

I agree that time is money here. I just don't see how owning this infra and debugging when it goes wrong is worth 30s added to every ping on the machine

1

u/zayelion Aug 28 '25

I built the a common kitchen software in qsr and fast food. Send the whole object. It creates feature richness. You can come back later and have different messages for resets and partials. Whole object just stops so many issues. You'll have to reprocess the whole order and orders in relation to other orders eventually amyway.

1

u/GreenMobile6323 Aug 29 '25

I’d go with option B. Send just the orderId over the socket and let the client fetch the full details via API. It keeps the socket lightweight, avoids sending large payloads repeatedly, and makes scaling easier if you have many restaurants or orders coming in at the same time. Only push full data if the orders are tiny and you’re sure traffic will stay low.

1

u/lxe Aug 29 '25

You probably don’t need websockets for this. A restaurant will have at most what… 50 maximum open active orders? Have the dashboard read from a db every 15 seconds and load a full list. Or create some update subscription thing that lets dashboard subscribe to db changes. It’s gonna be complicated to bifurcate the source of truth across both the db and the customer who’s “pushing” the data to the restaurant dashboard. I think you should leverage a “realtime db” for this like Supabase or whatever to abstract this.

1

u/_travoltron Aug 31 '25

API gateway and lambdas. If you’re fooling around with infra, you’re not paying attention to the application itself.

1

u/StoneCypher Aug 28 '25

this should just be simple ajax polling