Food Service Architecture (2 Part Series)
My wife and I used to work in food service together (Chili's and Gordon Biersch). When we're in restaurants we like counting how many tables each waiter has, how many employees are on staff vs how many customers are on the floor, manager count, etc.
Recently I've started being able to draw connections between our observations in different restaurant's setups, and common application designs/tools. Some of these end up being crazy thought experiments, like "what is the food service equivalent of Cloud Services?". It's often surprising how many parallels can be drawn.
So here's a few of these thought experiments:
A monolithic application is one that is built to handle everything the company needs within one application. Micro services are smaller applications designed to focus on very specific tasks.
The most common example of monoliths in the food service world is coffee shops. The employees in most coffee shops are expected to be able to handle any task that would be needed for them, and often switch between different tasks (handling the register one moment, making coffee the next, cleaning up plates/trash later on).
These employees generally have roughly the same resource cost (hourly pay), so even if you just need a new employee to help clean up trash, you have to pay the standardized cost of an employee. Teams like this generally would be easier to manage though, since there is not too much deviance between each employee (outside of personality).
Micro services in food service are more common in sit down restaurants. Employees are trained in and assigned specific roles: Waiter, Food Runner, Busser, Cook, Dishwasher, Host, etc.
The primary benefit in these roles is how easy it is to scale individual tasks. If un-bussed plates are being a bottleneck for performance, you can place more bussers on the floor, without impacting any of the other roles (waiters, hosts, etc.). Since the expected work of each role is more granular, training also becomes simpler. You don't need to teach a dishwasher how to gracefully handle a table complaining that their Sushi is raw.
The trend tends to be to try and aim for micro services over monoliths. Designing applications to be solely focused on their specific tasks lets you make changes without worrying too much about impacting functionalities in other applications, and often fits better with having multiple development teams working separately from each-other.
That being said, just like in the above scenarios, monoliths have a very strong niche in small companies that have a very limited functionality set that needs to be supported. The reduced complexity can save many development hours/meetings, which for small companies and startups is fairly important.
Caching is essentially keeping track of the answer to a question in case that question gets asked again.
This one is pretty subtle in food service, but can be impactful. When a customer in a coffee shop asks for skim milk, and the barista goes to get the milk, they may find that the shop is out. This may happen for a few baristas before they just write up on the menu "out of skim milk". Many POS systems also enable the manager to not let employees ring in a certain item they are out of, so the question never makes it back to the cooks.
Now if someone goes out and gets skim milk, but doesn't clear the message off of the menu, people will still think they are out of skim milk. The cache has an old, now incorrect, answer to the question.
A push model is one where each an application tells another application information.
A pull model is one where an application needs to ask another application for information.
This is actually an interesting one in the food service world. Most sit down restaurants follow a pull model. It is expected that the waiter will check up on the customer and ask them if they are ready or need anything. So a waiter will often spend a lot of resources (time, in this case, the most important resource for a waiter) checking up on the table and making sure they don't have any new information for the waiter. Much of what makes a good waiter good is knowing how to pace these checkups, as doing it too often can be taxing on both the customer and the waiter, while doing it not enough can make the waiter be delayed in missing important new information (drinks need refilled).
One of the most traditional implementations of a push model I've seen is diners. For the most part in a diner, waiters don't spend as much time checking up on the status of a table. They instead make sure that they are available/present reliably in case a customer needs to give them information (sending a command, in tech terms).
Most diners additionally have the customer pay up front instead of paying at table. This is essentially the waiter pushing a "pay bill" command to the customer. At this point the waiter does not need to spend any resources (time) checking up on the customer, unless the customer requests something from them (sending another command). The customer then, on their time, brings the check to the front desk (essentially sending their own "pay bill" command to the front desk). This distinction in how bills are paid is often the difference between a waiter being able to take 6-10 tables at once (as diners often do), and being limited to 4-6 tables (as most 2-3 star restaurants do).
There's also been a trend of using table side tablets for customers ordering food lately. This is another example of a customer being able to push a command to a waiter (or sometimes directly to the kitchen), without the waiter needing to pull/check up on them.
From an application standpoint, you generally want to make sure that commands are getting pushed instead of information being pulled/polled. This will avoid delays in information being up to date from a scheduled synch job, and can often avoid bottlenecks caused by slow queries.
There are, however, many situations where you cannot avoid pulling information or polling for a check up.
Load balancing is when you have many applications that do the same job, and have an application sitting in front of them distributing the work.
The host is often the load balancer of restaurants. There are generally many waiters working the floor, and if customers are given free rein of where to sit they can end up all sitting in the same waiter's section, causing that one waiter to become over taxed while other other waiters have nothing to do. Or worse yet, they can go to a section where the waiter is not available for whatever reason (on break, closed section, etc.). It's the hosts job to know how many waiters are in rotation and how strained they may be.
This is actually a direct translation to how a load balancer actually works. Most websites you look at are set up behind a load balancer. There may be hundreds of servers that you could potentially be hitting, but the load balancer keeps track of which ones are currently active, which ones may be overstrained (or having errors), and will direct traffic to the server it finds appropriate.
This is an ongoing thought experiment, I'm already cooking up more comparisons for a future article (hopefully within the next week or so). Stay tuned for more!