The Most Dangerous Words in Software Engineering: “We All Agree”

# softwareengineering# leadership# architecture# career
The Most Dangerous Words in Software Engineering: “We All Agree”ivan.gavlik

I once let a consensus convince me that a decision was right simply because the people supporting it...

I once let a consensus convince me that a decision was right simply because the people supporting it were smarter and more experienced than I was. Months later, I realized the problem wasn't that we lacked knowledge. It was that nobody seriously tried to prove wrong.

The Problem

A few years ago, I was part of a project to modernize an existing application. The system worked. People used it every day, and the business depended on it. It wasn't perfect. We had technical debt, parts of the codebase nobody wanted to touch, and deployments that occasionally required more attention than they should have.

But it worked.

During one of our architecture meetings, we proposed breaking the existing application into microservices. The idea sounded great. Better scalability, independent deployments, clearer boundaries between domains, and the ability for teams to develop different parts of the system without blocking one another.

The meeting included our CTO, a system architect, and several senior engineers. We all had years of experience. Some had worked on systems processing millions of requests. Others had been through major migrations. A few were known for spotting architectural problems before the rest of us even realized there was a problem.

After few discussions, we all agreed.

I remember thinking that this was a good sign. When so many experienced engineers agree on a technical decision, surely we've done our homework.

I'm not so sure about that assumption anymore.

How We Made the Decision

At first, everything looked professional. We prepared a presentation, drew the architecture, defined service boundaries, and discussed the technologies we would use. Every argument in favor of microservices sounded reasonable.

The problem was that almost nobody asked the most fundamental question:

What specific problem are we experiencing today that this architecture would solve, and that we couldn't solve with a simpler approach?

We weren't struggling to scale individual parts of the application independently. We didn't have dozens of teams constantly blocking one another. We had no meaningful data showing that our existing architecture was preventing us from delivering features.

We had technical debt and a feeling that the system should look more modern.

Those are not the same thing.

Still, the decision had already gained momentum. One colleague explained how microservices had solved similar problems at a company where he'd previously worked. Another mentioned several well-known tech companies using the same architecture. Our CTO supported the direction because it aligned with the long-term vision for the product.

Each argument sounded convincing on its own. Together, they created the impression that we'd reached an inevitable conclusion.

I had some doubts. I wondered whether the operational complexity would outweigh the benefits, but I didn't push very hard. Everyone else seemed confident, and I didn't have enough concrete evidence to prove my intuition was justified.

Besides, I didn't want to be the person holding back progress.

At the time, I didn't realize how important that last sentence was.

When Consensus Becomes a Substitute for Reasoning

The migration took months.

We introduced service-to-service communication, separate deployment pipelines, additional error-tracking mechanisms, and new procedures for local development. Problems that previously required an understanding of a single application now sometimes required us to understand several services, their communication patterns, and the state of their data.

Every new service boundary introduced another way for something to go wrong.

Of course, microservices weren't solely responsible for every problem we encountered. Some difficulties came from the way we implemented them, while others were simply the natural challenges of distributed systems. But increasingly, we were spending time on infrastructure and coordination instead of building the features our product actually needed.

Whenever we encountered a problem, we almost always discussed how to improve our microservices implementation. We rarely returned to the question of whether the original decision had been justified in the first place.

It was as if the decision, once made and validated by consensus, had become a fact that no longer needed questioning.

I remember one meeting where we were trying to solve a problem with the speed of feature development. A colleague suggested introducing another service to separate responsibilities more clearly.

Someone said it was the logical next step.

Others agreed.

And for the first time, I seriously thought: Wait a minute. Weren't we trying to solve a problem that we had partly created ourselves?

I didn't say it immediately. I watched the discussion unfold and noticed something I'd previously overlooked. Nobody was deliberately defending a bad decision. Everyone was trying to do their best within the assumptions we'd already accepted.

Our problem wasn't intelligence. It was the framework within which we were thinking.

Why Didn't Anyone Seriously Object?

For a long time, I thought the explanation was simple: we should have been smarter and analyzed the architecture more carefully.

Today, I think that's only part of the story.

First, there was authority. When the system architect and CTO support a particular direction, it's not easy to be the person who openly challenges it. Even when everyone is formally allowed to express an opinion, hierarchy influences what people actually say.

Second, there was professional reputation. Nobody wanted to look like someone who didn't understand modern architectural patterns. If microservices are a symbol of maturity and scalability, opposing them can easily look like resistance to change.

Third, we shared many of the same information sources. We read similar articles, followed the same technology trends, and talked to people with similar experiences. We thought we had multiple independent confirmations, but we were often hearing different versions of the same arguments.

Finally, nobody had much incentive to challenge the decision seriously. There was a migration plan, a budget, and a deadline. Stopping the project would have required an uncomfortable conversation about whether we'd made a mistake.

And so consensus began to take on a life of its own.

Nobody had to lie. Nobody had to apply direct pressure. It was enough that we all believed the others had already verified what we'd only partially examined ourselves.

What I Learned About Consensus

I used to believe that consensus among experienced engineers provided an additional layer of confidence. If enough competent people agreed, we were probably on the right track.

I still think that's often true.

But I've learned to distinguish between two ways consensus can emerge.

In the first, people independently analyze a problem, exchange arguments, challenge their own conclusions, and eventually arrive at the same result. That kind of consensus is valuable because it emerges from a genuine process of verification.

In the second, people share an initial assumption, rely on authority, or follow a professional trend. Their conclusions may be sincere and mutually consistent, but their agreement doesn't represent as many independent confirmations as it appears to.

The difference is enormous.

If ten engineers agree that a particular architecture is best because each has independently analyzed our requirements, that's a meaningful signal.

If they agree because the most influential person in the room said it was the best solution first, and everyone else mostly built on that person's arguments, we're dealing with something very different.

The number of people who agree is not the same as the number of independent reasons to believe they're right.

That realization also made me reconsider my own behavior. How many times had I accepted a decision because it sounded sophisticated, modern, or widely accepted? How many times had I kept a concern to myself because I didn't want to appear incompetent? And how many times had I used my experience to justify a conclusion I hadn't properly verified?

I didn't like the answers.

How I Approach Technical Decisions Today

I no longer try to disagree with my team just to prove that consensus can be wrong. That would simply be another version of the same problem: making decisions based on social dynamics instead of the quality of the arguments.

Instead, I try to change the questions we ask.

When someone proposes a new technology or architecture, I first try to understand the problem we're attempting to solve. I don't just ask about the advantages of the proposed solution. I also ask which assumptions must hold true for those advantages to materialize.

I encourage the team to consider at least one alternative. Not because that alternative must be better, but because comparing different approaches often reveals costs we would otherwise overlook.

When uncertainty is high, I'd rather run a small experiment than attend another meeting where everyone exchanges opinions. If we can measure the system's behavior, build a prototype, or test an assumption, we should do that.

And increasingly, I ask a question that once seemed unnecessary to me:

What would we need to learn to change our minds?

If we can't answer that question, perhaps we haven't clearly defined the criteria by which we'll evaluate our decision.

This doesn't mean turning every technical decision into a scientific experiment. Time is limited, and some decisions simply aren't that important. But the more expensive, long-lasting, and difficult to reverse a decision is, the more important it becomes to understand what it's based on.

The Most Important Lesson

Today, when an entire team agrees on a technical decision, I don't automatically feel more confident than I used to.

Instead, I'm interested in how we reached that agreement.

Did we verify our assumptions? Did we consider alternatives? Did anyone seriously try to find a reason the decision might be wrong? Did people who disagreed have enough room to speak up?

I don't expect someone to oppose every decision. Nor do I expect every minority opinion to be better than the majority view. Sometimes we agree because the solution really is good. Sometimes a discussion has already demonstrated that a particular alternative doesn't make sense.

But I want to know that our agreement is the result of scrutiny, not the absence of resistance.

Ultimately, the biggest change has been in how I understand my own role as a senior engineer.

I used to think a senior engineer was expected to have answers, recognize the best solution, and convince others to accept it.

Today, I think an equally important part of the job is recognizing when a team is becoming too confident in something it hasn't adequately verified. It's about creating an environment where a junior engineer can challenge an architect, where a CTO can change their mind, and where changing your position isn't a sign of weakness but a consequence of better understanding the problem.

Technical decisions don't become good simply because experienced people made them. They become good when the reasoning behind them is strong enough to withstand serious scrutiny.

The best team isn't the one where everyone agrees. It's the one where anyone can try to prove a decision wrong without having to fear for their position.