What Running Hardware in Mexican Restaurants Taught Us About Production Software
15% of the codebase, 40% of the production incidents. What thermal printers, dynamic screen stations, and kitchen displays taught us about building software for physical environments.
By Igor Riera
Software engineers tend to think production means “the code is deployed.” In restaurant tech, production means a Star TSP143IV thermal printer, a $35 dynamic screen puck, and an Elo touchscreen - in a kitchen that hits 40 degrees Celsius, on WiFi shared with the security cameras and the Spotify playlist.
PayTable is a QR ordering and payments platform we operate in Mexico. The software side - .NET 9 backend, Vue 3 PWA, Azure infrastructure - is complex enough. But the hardware layer is where the product lives or dies, because a restaurant that can’t print a ticket at the right station doesn’t care how clean your architecture is.
The Printer Problem
We use Star TSP143IV thermal printers with CloudPRNT. The protocol is straightforward: the printer polls our server at a configurable interval, checks for pending jobs, and prints what it receives.
The requirement is simple - order placed via QR, ticket prints in the kitchen within 2 seconds. If that number drifts to 10 seconds, the workflow breaks. Waitstaff walk to the kitchen to check if the order arrived. The ordering app stops being a tool and becomes extra overhead.
What makes this hard:
The printer is on the restaurant’s local network. Our server is in Azure. The poll interval is the printer’s decision - we don’t push to it. If the restaurant’s WiFi dips, the printer misses a poll cycle. If multiple orders land between polls, they queue and print in a burst. If the printer runs out of paper, it buffers silently until someone notices.
We built a heartbeat monitor on the server side. If a printer misses three consecutive poll intervals, the admin dashboard flags it. The waiter app shows a printer status indicator. These aren’t features we planned - they’re features that production demanded after the first week of real service.
Dynamic Screen Table Identification
In some instances, tables in a PayTable restaurant have a dynamic screen station. Customer scans a dynamic QR with their phone, the system identifies the table, and serves the right menu. The kitchen ticket includes the table number. The waiter app shows which tables have active orders.
The pucks themselves are simple - screens with a URL payload that opens the PWA with a table identifier. The complexity is environmental. Restaurant tables get wiped down every service. The adhesive holding the dynamic screen station fails in humid kitchens. Customers spill drinks on them. Children peel them off.
We went through three mounting solutions before landing on recessed housing that the restaurant installs into the table surface. It costs more per unit but the replacement rate dropped from weekly to quarterly.
The firmware side is minimal - these are simple dynamic active devices, but the URL routing they trigger has to be bulletproof. A dead link or a slow-loading PWA at the moment a customer scans is a lost order. We preload the menu data aggressively and cache it on the device.
Kitchen Display Systems
Elo touchscreen computers run our kitchen display application - a custom Kotlin app in kiosk mode on Android 14. The display shows incoming orders, lets kitchen staff mark items as in-progress or complete, and updates the waiter app in real time via SignalR.
Each Elo device polls the server for order updates. At one restaurant with one device, this is trivial. At 2,000 restaurants with multiple stations each, every poll is a database hit. Our early implementation used direct database queries on every poll. Under load testing, this was one of the first things to break.
We moved to a SignalR-based push model for order updates and kept polling only as a fallback for reconnection scenarios. The reduction in database load was immediate - and it eliminated the 2-3 second lag that kitchen staff noticed between an order being placed and appearing on screen.
What None of This Looks Like in a System Diagram
Architecture diagrams show boxes and arrows. They don’t show that the arrow from “Server” to “Printer” goes through a restaurant’s consumer-grade WiFi router that restarts itself every night at 3 AM. They don’t show that the “Dynamic Screen Puck” box is a $35 plastic puck fixed to a table in a city where the humidity averages 75%.
The hardware integration code in PayTable is maybe 15% of the total codebase. It accounts for about 40% of the production incidents. Every device has its own failure mode, its own firmware version, its own environmental constraints. The thermal printer’s paper sensor behaves differently when the ambient temperature changes. The Elo touchscreen’s capacitive touch layer responds inconsistently with wet fingers - common in a kitchen.
Scaling Hardware
We’re targeting 2,000 restaurants for the 2026 World Cup. That’s not 2,000 software deployments - it’s 2,000 sets of physical devices that need to be configured, installed, connected, and monitored.
Each restaurant needs at minimum: one thermal printer, one dynamic screen station per table, one kitchen display. Most need more. A restaurant with 20 tables and two kitchen stations is 23 devices, each maintaining a connection to our backend.
The monitoring infrastructure for hardware had to be built from scratch. Cloud monitoring tools know how to watch a container’s memory usage. They don’t know how to watch whether a Star TSP143IV in Cancun missed its last three CloudPRNT polls.
We built device health dashboards into PayTable’s admin interface. Printer status, dynamic screen station last-seen timestamps, kitchen display connection state. Restaurant managers don’t need to understand the technology. They need to know whether their kitchen is going to get the next ticket.
The Lesson
If you’re building software for physical environments, the hardware isn’t an integration. It’s the product. The Vue PWA is the interface. The .NET backend is the engine. But the thermal printer, the dynamic screen puck, and the kitchen display are where the system touches reality - and reality doesn’t follow your retry strategy.
Build the monitoring first. Test in the environment, not the lab. And budget twice as much time for hardware as you think you need, because the failure modes are physical and the debugging requires being in the room.