The header team

On micro-frontends and our inability to avoid stupidity.

House of cards

Photo by Yannick Pulver on Unsplash

What is micro frontends?

If you want to know, read about it here.

Otherwise, let me summarize it for you in a short paragraph.

MFE (micro frontends) is a way to let decoupled teams work on different portions of a webpage, kinda asynchronously, without stepping on each other's toes. They do it by developing separate, isolated "apps" for, say the header, the footer, the product listing, etc. (hence the title of this essay). The proponents of MFEs claim that this leads to loose coupling, easier incremental development, and better reusability.

Micro frontends are the logical continuation of the microservices trend but applied to user interfaces.

Give me five minutes to convince you how counterproductive this approach is to non-enterprise-level teams.

Disclaimer: I've been a part of a similar software development process. Even though we never called it micro-frontends, it was my worst experience ever in this industry. So, I'm talking from experience in a way.

Loose coupling

The holy grail of software development. The wet dream of the programmer nerd.

I'm going to assume you already know what loose coupling is and just go straight to my point.

LC is the root of most evil in software development. It's also the root of MFEs.

It might sound like I'm trying to be controversial, but it's quite the opposite. I'm trying to be rational here.

When does loose coupling become dangerous

Let me step back.

Loose coupling is not wrong in itself. It's a good practice to keep your modules separate and isolated to some extend. That way you are not only isolating the module's state and behavior. You're isolating units of complexity in a larger context.

Many problems arise when, to tame some complexity and put it in a box, it gets accidentally spilled out everywhere instead. And what's worse, it happens in an unexpected, random fashion.

Let me get concrete.

Say me and you are writing a book. We make a deal. I'll write the first five chapters, you'll write the last five. It makes sense, as we'll write the book faster, given we do it asynchronously. Also, I'll be focusing on my part of the story, and you'll be focusing on yours. We'll need to stay in sync, though, which is an acceptable tradeoff. We'll waste a couple of hours all in all, but the benefits justify it.

Imagine we're writing the same book, but we invite eight more people. Each one of us would have to write a single chapter. It's not going to be as smooth as if it was only the two of us. But we'll still manage to do it. We'll need more sync sessions, as we'll have to be extra careful not to kill somebody in chapter five and bring him back to life all of a sudden in chapter seven.

I know that you know where this is going. But let me continue.

Let's write the book, one sentence at a time. Let's invite hundreds of thousands of people and assign them a simple task. Write a single sentence in the context of the whole story. What do you think? Is it micro enough to see how crazy this sounds?

Going micro leads to macro problems

Developing micro-whatever sounds micro only on the surface.

Going down the micro-whatever spiral, you gradually start losing context. That's acceptable to a certain degree. It's even necessary for systems design. But at some point, it becomes exponentially dangerous for the whole company and the individual engineers themselves.

Micro frontends are way beyond that tipping point.

We could make the argument that teams would resolve the distributed lack of context through better communication, better upfront design and planning, and lots of specs that somebody would have to write.

And this is where things start to fall apart into an unmanageable pile of "loosely coupled" entities.

The more context you lose on the level of the individual module, the more coordination work is needed on the upper levels.

Some things are meant to be coupled

Entities imply coordination.

Coordination requires resources - time, people, money.

Ultimately, you'd want to achieve a well-balanced system with a couple of well-defined, properly isolated modules that live in the context of the whole. The general principle is this: the more coupling - the less managerial work. The less coupling - the more meta work around keeping things in sync.

I firmly believe that a certain degree of coupling in a system is vital! Tightly coupled modules are not only safe most of the time. They are less dangerous in certain scenarios than loosely coupled ones. For example, when you have to move fast. Or when you have to deal with some cross-cutting concern in your system.

If we were to leave the domain of software development for a moment, we'd see examples of coupling everywhere. Our homes are tightly coupled. Our bodies are tightly coupled. Things live in context, not in a vacuum. There's a reason for your heart to be well integrated inside your body and not some decoupled object, which you could put in your pocket in the morning and leave on the shelf when you get home.

Principle of parsimony

When in doubt, go back to basics. And what better basics than philosophy!

Let me introduce you to a simple heuristic, called the principle of parsimony, also known as Occam's razor. You might've heard people refer to it as a mental model, rule of thumb, or philosophical razor. A general thinking filter that allows you to quickly "shave off" unlikely explanations for a phenomenon, or avoid unnecessary actions.

A quick look at Wikipedia reveals the essence of the parsimony principle.

[...] the principle of parsimony or the law of parsimony (Latin: lex parsimoniae), is the problem-solving principle that "entities should not be multiplied beyond necessity" [...]

If you'd allow me to paraphrase it:

Whenever possible, don't introduce new entities.

Occam's razor maps perfectly to our use case. Micro frontends are in direct conflict with this principle. It's taking something quite straightforward as the UI of an application, and breaking it apart so that our company can brag about growth. But it's growth the wrong way, for the wrong reasons. Having a header and a footer team is a disturbing signal that resources are going in the wrong direction.

But I digress.

More entities, more exposure to downsides

It's mind-boggling how easily we agree to introduce massive, unlimited amounts of fragility to a system in return for a limited set of questionable benefits.

In Antifragile, Nassim Taleb discusses the concept of asymmetry.

Anything that has more upside than downside in the context of a random event is more than robust. It's antifragile. In other words, it gains from disorder. It gets better when bad things happen to it.

The software world is full of disorder, yet we never learned to limit the downside in our quest for the holy upside.

I love what Charlie Munger has to say about this kind of stupidity:

It is remarkable how much long-term advantage people like us have gotten by trying to be consistently not stupid instead of trying to be very intelligent.

Micro frontends are simply trying to be very intelligent.

Micro frontends work in some cases

I bet that some companies hugely benefit from the micro frontends approach.

But these companies are already massively complex in structure. The managerial work they have to do daily is monstrous. The software they produce is anything but trivial. And anuything but trivial things require unusual approaches.

For the vast majority of software (99.9%), micro frontend is a step in the wrong direction.

It is technical complexity leaking into non-technical domains (managerial).

I don't have any advice on when to reach out to MFEs. It's highly contextual. But in 99.9% of the time my default response, without even knowing what you're developing, would be don't introduce a header team, it's dangerous.