← Back to Operating Notes

Operating Notes

Why most internal software projects fail (and how to approach them differently)

The breakdown usually happens before anyone writes production code. Here is how problems get mis-defined, why internal tools are not products, and what a grounded build looks like.

12 min read

Problem

Most internal software doesn't fail because of code

It fails before that.

The problem is rarely technical execution. It's how the problem is defined in the first place. A team identifies friction—manual work, disconnected systems, inconsistent data—and decides to "build something." The intent is right. The approach is usually not.

Requirements get written too early. Assumptions go unchallenged. The system is designed around what people think they need, not how the work actually behaves.

By the time development starts, the shape of the solution is already off.

Why it happens

The real issue is abstraction too early

Most internal systems are designed from a distance.

Workflows are simplified on paper. Edge cases are ignored. Variability is treated as noise instead of signal. The result is a system that looks clean, but doesn't fit.

So teams adapt: workarounds get introduced, manual steps reappear, spreadsheets return to fill gaps. The system exists—but the work happens somewhere else.

Internal tools are not products

This is where many teams get stuck.

They treat internal systems like customer-facing products: over-designed interfaces, unnecessary flexibility, features that anticipate future needs.

But internal systems serve a different purpose.

They don't need to be broad. They need to be correct. They should reflect how the work actually happens—not how it might happen in theory.

That means fewer abstractions, tighter workflows, and decisions embedded into the system.

What actually works

Good systems are shaped by use, not speculation

The right approach is not to design everything up front. It's to get close to the work and let the system emerge from it.

That usually looks like:

1. Start with a real workflow

Not a diagram. A real process with real constraints.

2. Identify friction points

Where time is lost, where errors occur, where decisions are unclear.

3. Build narrowly

Solve a specific part of the problem well, instead of solving everything broadly.

4. Expand based on use

Let real usage shape what comes next. This reduces risk and produces systems that actually get used.

Most value comes from smaller systems

There's a tendency to think in terms of large platforms or full replacements.

But in practice, the highest leverage often comes from:

  • connecting two systems that don't talk
  • removing one manual step from a critical workflow
  • making key data visible in one place
  • enforcing consistency where it matters

These changes are not dramatic—but they compound. Over time, they reshape how work gets done.

Where projects usually go wrong

Repeated failure patterns

Trying to solve everything at once

Scope expands, timelines slip, and the system becomes harder to reason about.

Designing for edge cases too early

Complexity increases before the core workflow is stable.

Losing proximity to real work

Decisions are made without observing how the system is actually used.

Treating the system as "done"

Instead of something that should evolve with the business.

What good looks like

When an internal system is working

  • It fits the workflow without constant adjustment
  • It reduces decision friction
  • It makes the next step obvious
  • It handles variation without breaking

Most importantly, people use it without needing to be told to.

Related notes

Need clarity on a system, workflow, or technical decision?

Start with a Fit Check to talk through what is working, what is fragile, and what needs a clearer path forward.

Book a Fit Check