Human Shaped Microservices

Human Shaped Microservices

Photo by Daniel Bradley on Unsplash

Imagine you’re at a restaurant. You sit down, the waiter comes over, and you ask if you can order a burger.

The waiter nods, turns around, walks to the kitchen, leans over the pass, and asks the chef: “Do we have burgers?”

The chef checks. “Yeah, we’ve got burgers.”

The waiter walks back. “Yes, we have the burger.”

You order it.

The waiter walks back to the kitchen, puts in the order, and then… stands there. At the window. Waiting. While the chef cooks your burger.

The whole time, that waiter isn’t taking any other orders. Isn’t checking on other tables. Just standing at the pass, staring at the chef, waiting for your food to be ready.

When it’s done, the chef hands it over. The waiter carries it to your table. Job done.

Except the table in the corner has been trying to get someone’s attention for ten minutes.

The kitchen just ran out of fish.

The person trying to order it is waiting for the answer back from the kitchen.

And the process repeats.

And your waiter is back at the window again, waiting on someone else’s steak.


This is absurd. No restaurant works this way.

But this is almost exactly how so many people build software systems.


Real restaurants work differently.

When they’re running low on fish, someone calls it out. By the time the last portion goes, the floor staff already know. Not because they asked, but because the kitchen told them when it mattered. Nobody has to walk back and check. The state change is announced.

Orders go in on a ticket. The kitchen works through them. When something’s ready, the bell rings. A waiter, whoever’s free, collects the food and takes it out. The chef doesn’t wait for a specific waiter. The waiter doesn’t stand frozen looking into the kitchen. Everyone keeps moving.

The whole floor runs asynchronously. Information flows when it changes. Nobody blocks waiting for a response to a question they shouldn’t need to ask.

Now think about your services.

When Service A needs to know if inventory is available, does it call Service B and wait for an answer? When something changes; an order ships, a payment clears, stock runs low, does every other service have to ask? Or does the system tell them?

So many of the architectures I’ve seen work like the bad restaurant. Services stand at windows, waiting. They ask questions they could have been told the answer to. Requests stack up. Everything slows down together, because everything is coupled to everything else. Deployments get harder, failures cascade, a retry framework gets added with blind hope.

The fix isn’t a different framework. It’s a different model.

If you imagined your system as teams of people, how would they communicate? How would they divide the work? How would they scale up when things got busy?

Effective teams send a message or pass a packing slip, giving the other team the information they need to do their job. They’d ring a bell or pass another message when something was ready, or something was running low.

That’s the intuition behind what I call Human Shaped Microservices: model your services the way you’d organise humans doing the same work. The communication patterns, the division of responsibilities, the way information flows, all of it.

When you do that, async messaging stops being an abstract architectural preference and starts being an obvious choice. Of course services communicate through events. That’s how people communicate. That’s how work actually flows.

The restaurant doesn’t make the waiter stand at the window. The kitchen doesn’t wait to be asked if they’re out of fish.

Neither should your software.

I’ve been thinking about it this way for long enough that I built a .NET messaging library around it; Nimbus. That was 13 years ago, before anybody was using really using the term microservices.

In the posts ahead I’ll dive into the patterns that fall naturally out of this approach, commands, events, and sagas - and the anti-patterns that appear when the modelling goes wrong. First up: the entity service, the single most common reason a well-intentioned microservices migration ends up slower and harder than the monolith it replaced.

The Nimbus Messaging API Is Back
Older post

The Nimbus Messaging API Is Back

Comments

Reply to this post on Bluesky to leave a comment.