Two engineers arguing in front of a whiteboard filled with messy diagrams

I’ve sat through enough sprint planning sessions to catch the stench before the first pull request even hits the repo. The real screw-up in engineering teams isn’t a busted algorithm or some memory leak. It’s the invisible gunk—assumptions, office politics, and flat-out laziness—that hardens weeks or months before anyone types git init. We obsess over linters and test coverage while the foundation is made of Swiss cheese, glued together by a product manager’s wishful thinking and an architect’s midlife crisis.

Here’s the part nobody says out loud: if your engineering org feels like a dumpster fire, you probably struck the match during planning, not during the sprint. The code is just the crime scene. The actual murder happened earlier, in a conference room that reeks of stale coffee and broken promises.

The “Requirements” Document That’s Really Just Fan Fiction

Most so-called requirements docs aren’t requirements at all. They’re a pile of fuzzy business wishes, user stories written by someone who’s never met a user, and acceptance criteria that basically say “make it work good.” I’ve seen 40-page PRDs that spend 10 pages on the color of a button but never define what happens when the primary API returns a 500. That’s not planning. That’s creative writing with a project management tool.

The dysfunction takes root the moment engineers nod along to a spec that’s got more holes than a block of Emmental. Why? Because saying “looks good” in the meeting is easier than spending an hour wrangling edge cases with a product owner who just wants to update their roadmap slide. Fast-forward three sprints, and you’re refactoring the entire authentication flow because nobody asked what “user” actually means when you’ve got multi-tenant accounts. Classic.

Technical Strategy by Hype Cycle

Engineering leadership picks technology the way a teenager picks a prom outfit: whatever’s shiny and racked up upvotes on Hacker News. Microservices? We’ll do that. Event sourcing? Why not. Kubernetes on bare metal, managed by a team that can’t even keep a cron job running? Ship it.

The tech itself isn’t the problem. The problem is that the decision gets made in a vacuum, usually right after a CTO watches a conference talk and feels insecure. The architecture gets sketched as boxes and arrows on a diagram that looks like a subway map drawn by a lunatic. Nobody stops to ask, “Do we actually need to solve this, or are we just bored?” By the time the code gets written, the team is already locked into a complexity death spiral. The real requirements—sub-100ms latency, zero data loss, actual uptime—never made it into the conversation. The dysfunction is baked into the architectural DNA before the first Docker container gets built.

A frustrated developer staring at a complex architecture diagram on a monitor

Team Topology as an Afterthought

Conway’s Law isn’t a suggestion. It’s a threat. If your org chart looks like a feudal hierarchy with overlapping fiefdoms, your software will look exactly like that. I’ve consulted for companies where two teams owned adjacent parts of the same feature but literally never spoke to each other. They communicated through Jira tickets and passive-aggressive comments in a shared Slack channel. The integration points were a disaster because the contract between their services boiled down to “whatever we feel like deploying today.”

This starts months before anyone writes a line of code. It starts when a VP splits a team based on headcount instead of actual system boundaries. Or when they hire a “Principal Architect” who locks himself in a room for six weeks and emerges with a 200-page design document nobody else had a say in. The dysfunction is social, not technical. You can’t fix it with nicer pull request templates. You fix it by admitting that how people talk to each other is a first-class architectural concern.

The Invisible Tax of “Temporary” Decisions

Every engineering org has a graveyard of temporary decisions that turned permanent. The weekend prototype now handling production traffic. The database schema that was “just for the MVP” but now has 50 tables and zero foreign keys. The authentication hack everyone swore they’d replace within a quarter—it’s been three years, and the CTO still gets paged when it breaks.

The dysfunction here isn’t that people take shortcuts. It’s that the organization has no way to pay back technical debt. The planning phase treats these decisions like they’re free, as if a “quick and dirty” solution won’t rack up interest. When the real coding starts, the team is already carrying a backpack full of rocks, and nobody budgeted time to take them out. The result is a codebase that’s 40% workarounds for earlier workarounds. That’s not bad engineering. That’s bad planning wearing the mask of pragmatism.

How to Spot the Rot Before It Stinks

You don’t need a crystal ball. You just need to stop lying to yourself during sprint zero. Here’s my checklist for sniffing out pre-code dysfunction:

  • Ambiguous language: If the spec uses words like “flexible,” “scalable,” or “resilient” without concrete numbers, you’re already hosed. Demand percentiles, throughput, and actual error budgets.
  • No failure modes: If the design document doesn’t have a section called “How This Can Break,” it’s a fairy tale. Real engineers think about the unhappy path first.
  • Hero culture: If the plan depends on one person who “knows the whole system,” you’re building a single point of failure, not a piece of software.
  • Date-driven deadlines: If the launch date was set before the scope was defined, the code is going to be a hostage situation, not a craft.

A team of engineers in a tense meeting, looking at a timeline on the wall

None of this is rocket science. It’s just that most orgs are too busy cosplaying as “agile” to actually have the hard conversations. Standups become status theater. Retros become blame sessions. And the real technical problem—the one between our ears and inside our org charts—gets ignored because it’s uncomfortable.

FAQ

Why do smart engineers keep falling into these traps?

Because intelligence has nothing to do with it. The traps are cultural and institutional. Most engineers are trained to focus on the code, not the system that produces the code. Add a layer of middle management that rewards consensus over correctness, and you get a recipe for collective self-deception. It’s not a bug; it’s a feature of how companies are structured.

Can a good engineering manager fix pre-code dysfunction?

Yes, but only if they’re willing to be the unpopular one in the room. A good EM has to say “no” to unrealistic dates, push back on half-baked requirements, and protect the team from the organizational chaos. That takes political capital and a spine. Most managers prefer to keep their heads down and hope sprint velocity will magically fix everything. It won’t.

What’s the single biggest red flag during project planning?

When nobody can clearly articulate the problem the project is supposed to solve. If the conversation is all about the solution—“We’re going to use Kafka!”—without a tight definition of the actual user pain or business need, run. The code hasn’t been written yet, but the dysfunction is already fully operational.