Chapter 5: The Tribal Wars
Vim vs. Emacs. React vs. Vue. Rust vs. Go. The weapons change, but the war never does. And nobody ever asks: what are we actually fighting about?
You’ve seen the arguments. You’ve probably been in them.
Someone posts a benchmark showing Language A is faster than Language B. Someone else posts a different benchmark showing the opposite. Within an hour, the thread has two hundred replies, most of them generating more heat than light, and at least three people have called each other’s language a “toy.”
On the surface, these look like technical disagreements. Two groups of engineers, presenting evidence, debating trade-offs. But if you’ve been around long enough, you know that’s not what’s actually happening. What’s happening is much older, much deeper, and much more human than a disagreement about garbage collection strategies.
What’s happening is tribal warfare.
The Oldest Game
Humans have been forming tribes since before we had language to describe it. In-groups and out-groups are among the most fundamental structures of human social organization. We form them around geography, ethnicity, religion, politics, sports teams, and — in our corner of the world — technology stacks.
The pattern is always the same. A group forms around a shared identity. The group develops norms, heroes, and language. The group defines itself partly by what it is and partly by what it isn’t — which means it needs an out-group, a “them” to contrast with. And once the in-group/out-group dynamic is established, every interaction between the groups gets filtered through that tribal lens.
In developer culture, the tribes form around technologies. But the tribal behaviors are universal. There’s the trash talk (“imagine still using [outdated thing] in 2025”). There’s the us-vs-them framing (“we value correctness; they just ship fast and hope for the best”). There’s the flag-planting (stickers, t-shirts, conference allegiances). And there’s the peculiar intensity of the arguments — intensity that makes zero sense if you think of these as technical disagreements, but makes perfect sense if you think of them as identity conflicts.
What You’re Actually Defending
When someone criticizes your framework and you feel a flash of anger, what is the anger about? It’s not about code. You can look at code dispassionately. You do it in every code review.
The anger is about belonging. When someone dismisses the technology you’ve built your professional life around, they’re dismissing the community you belong to, the skills you’ve invested in, the career choices you’ve made. They’re saying, implicitly, that the thing you chose — and therefore you, by extension — is lesser.
That’s why the arguments are so intense. That’s why a reasonable comparison of two JavaScript frameworks can devolve into something that looks, from the outside, like a religious war. Because it is a religious war, in the oldest sense: a conflict between groups whose identities are threatened by the existence of a competing worldview.
You don’t get upset when someone says a screwdriver is better than a wrench for a particular job. You get upset when someone says the thing you’ve built your life around is wrong. And when your stack is your identity, any criticism of the stack is a criticism of the life.
The Roles We Play
Every tribal war has its roles, and developer culture fills them faithfully.
There are the zealots — the true believers who can’t acknowledge any flaw in their chosen technology and see any alternative as not just different but morally wrong. Their blog posts read like sermons. Their code reviews read like inquisitions.
There are the diplomats — the people who try to bridge the gap, who write “both tools have their place” posts that get a lot of polite nods and change nobody’s mind.
There are the mercenaries — the developers who use whatever they’re paid to use, who watch the tribal wars with bemusement, and who quietly do good work in any language without getting particularly attached to any of them. (These people are the heroes of this book, even if they don’t know it.)
There are the refugees — developers who switched tribes and carry a complicated relationship with both their old group and their new one. They understand things that lifers in either camp don’t, but they also feel a lingering guilt about leaving and a lingering need to justify why they left.
And there are the elders — senior developers who’ve been through enough wars to see the pattern. They remember when the current dominant framework was the scrappy newcomer and the previous dominant framework was supposed to last forever. They’ve watched enough “X is dead” articles to know that nothing ever really dies and nothing ever really wins. They’re tired, but they’re wise, and if you’re lucky, one of them will take you aside and tell you what they’ve learned: the wars don’t matter. The wars have never mattered.
The Cost of the Battle
Tribal wars aren’t just annoying. They’re expensive, and the currency is opportunity.
When you’re locked in a tribal stance, you can’t learn from the other side. And the other side almost always has something worth learning. The Vim people actually do have something to teach you about editing efficiency, even if you’ll never leave your IDE. The functional programming people actually do have insights about state management, even if you’ll never write Haskell in production. The Go people actually do have a point about simplicity, even if you find the language frustrating.
But you can’t hear any of that when you’re in battle mode. In battle mode, everything from the other side is enemy propaganda, and acknowledging any merit in their tools feels like treason.
The wars also poison communities from the inside. They create gatekeeping, where newcomers are judged not just on their skill but on their loyalty to the tribe. They create orthodoxy, where questioning the group’s consensus is treated as betrayal. They create an exhausting culture of performance, where you have to constantly demonstrate your allegiance through the right opinions, the right conference talks, the right tweets.
All of this energy — all of it — could be going into building better software. Instead, it goes into arguing about whether tabs or spaces is the One True Way.
The War Nobody Wins
Here’s the thing about framework wars: nobody has ever won one.
Has anyone ever been argued out of using React and into using Vue by a Twitter thread? Has anyone ever read a blog post titled “Why Go Is Better Than Rust” and thought, “You know what, they’re right, I’m going to rewrite everything”? Has anyone ever changed their technology identity because someone in a comments section made a really good point?
No. Because these arguments aren’t designed to persuade. They’re designed to signal. They tell your in-group that you’re loyal. They tell the out-group that you exist. They perform identity, and performance is their entire function.
The actual decisions — what to use for this project, what to learn next, what to build a career around — are made quietly, individually, in moments of honest self-assessment that look nothing like a Twitter war. They’re made by people who step outside the tribal noise long enough to ask: what do I actually need here?
Laying Down Arms
You don’t have to participate. You really don’t.
You can have preferences without having enemies. You can think TypeScript is great without thinking JavaScript is bad. You can love your stack without hating anyone else’s. You can be a member of a community without being a soldier in its army.
The developers who’ve figured this out are easy to spot. They’re the ones who say “I haven’t used that, but it looks interesting” instead of “that’s a toy language.” They’re the ones who can pair-program in an unfamiliar stack without treating it as enemy territory. They’re the ones who evaluate tools based on the problem at hand rather than tribal allegiance.
They’ve stepped out of the war. And the view from out here is a lot better.
Next: Chapter 6 - Why Learning a New Language Feels Like Betrayal