And why code-first custom software so often doesn’t.

There’s a pattern that shows up often in businesses that run on operational complexity, and it tends to end the same way.

A company hires a developer to build something custom — an internal tool, a management portal, an ops system. The developer asks what they want. The company describes it. The developer builds it. It works. At launch, everyone is pleased.

Six months later, the gaps appear.

Not critical failures — the software doesn't crash. It just doesn't quite fit. The workflow has an edge case the software doesn't handle, so someone made a spreadsheet for it. The reporting doesn't match how the team actually looks at the data, so they export to Excel. There's a multi-step process that the software treats as a single step, so people have developed a workaround. Over time, the workarounds compound. The spreadsheets multiply. The software works in the technical sense, but the operation has grown around it rather than through it.

A common failure mode in custom software is that the project captures requested features more clearly than it captures the operation those features are supposed to support. Competent teams can build the specified behavior correctly and still miss the business context that made the project necessary.

The code-first problem

Many software projects start with technology and feature language—what to store, display, and click—before the operational layer is fully recovered.

A client describes what they want. The team asks questions about features and data — what should the system store, what should it display, what should users be able to do. That is a natural language of software development. Entities, relationships, actions.

What it can miss is the operational layer: the way work actually flows through the business, the rules that govern decisions, the exceptions that happen regularly but don't fit the happy path, the informal processes people have developed because the formal process doesn't quite cover everything.

Software built primarily from a feature description can implement that description well and still leave gaps. The distance between "what was described" and "how the operation actually works" is where the workarounds live.

This is a harder problem than it sounds, because the operational layer is often invisible to the people inside it. If you've been running a warehouse for ten years, you don't think consciously about every rule and exception — you just know them. They're in your head, in the heads of your staff, in the informal protocols that developed over time. When a developer asks "what do you need the system to do," you describe the happy path. The exceptions surface later, in production, as gaps.

What operation-first looks like

On an active engagement, I started work on a rebuild of a legacy operations platform for a warehouse and inventory business. The existing system had been running for over a decade. It was built on a technology stack that hasn't been actively developed in years — a ColdFusion application backed by a database the client didn't own and couldn't export from directly. There was little usable documentation. One developer held much of the context. The client was effectively dependent on a person they were trying to move away from.

The technology problems were solvable. The more interesting challenge was this: nobody had formally documented how the operation actually worked.

The existing system captured some of it. But a decade of operational evolution had produced processes that existed around the system, not in it. Inventory decisions that got made in a particular order because of supplier relationships the original system didn't model. Grading criteria that had been refined over years but lived only in the heads of the people doing the grading. A check-in process that had three different workflows depending on where goods came from, none of which were explicitly documented anywhere.

Before significant implementation, I spent time learning the operation. Not just the features — the workflow. What happens at each stage. Who makes which decisions and based on what criteria. What triggers movement from one stage to the next. What the exceptions are and how they're currently handled. What rules are firm and what rules are guidelines.

That understanding became the specification. The specification became the software.

The difference, in practice: when the software ships, it is more likely to handle the exceptions. The grading workflows are modeled from observed operational reality, not only from a surface description. The multi-stage check-in process reflects how it actually runs. Edge cases that would have appeared as gaps months after launch can be designed in earlier—when they are cheaper to get right.

Why this is more important now

The rise of AI-assisted development has changed the cost structure of building software. A developer with the right tools can often build significantly faster than a few years ago. Work that once took a team longer can sometimes be delivered by a smaller group with better leverage—when the problem is well understood.

This is genuinely useful. It can make custom software reachable for businesses that previously couldn’t justify the cost.

It also amplifies the code-first problem.

AI coding tools are strong at executing against instructions. Given a clear specification, they can produce useful code quickly. They are weaker at owning whether that specification captures the full complexity of a real operational workflow—especially the exceptions and institutional knowledge that never made it into the brief. They build what they’re pointed at, and they can do it fast.

The result can be software that works at a surface level and misses operational depth—only now the misfit can appear sooner, because more features get built before anyone notices.

Starting with the operation isn't just good practice in an AI-assisted world. It's the difference between using AI tools to accelerate a build that fits and using them to accelerate a build that doesn't.

The documentation consequence

There's a second problem with code-first development that surfaces more slowly: the knowledge doesn't get captured.

When a developer builds from their own understanding of the system — understanding they developed through the build process — that knowledge lives in their head. The code implements it. The code is not the same as the documentation of why things work the way they do.

When that developer leaves, the knowledge leaves with them. The next developer looks at the codebase and sees what the system does. They don't see why specific decisions were made, what the exceptions were that drove certain designs, what the rules are that govern edge cases. They figure it out slowly, by reading code and making inferences. Or they make changes that break things they didn't know were load-bearing.

The company I mentioned earlier — the one with the decade-old legacy system — had exactly this problem. There was one developer who knew how everything worked. Not because he was withholding anything, but because nobody had ever built the practice of capturing that knowledge alongside the code. When the client wanted to replace the system, they couldn't safely migrate away without his involvement, because he was the only person who knew what the system was doing in places that weren't obvious.

On Stax-owned projects, that understanding becomes a Groundwork documentation set maintained throughout the build: architecture, data model, relationships, build map, code notes, design conventions, and codebase rules. Not written only after the project ships—built as the project is built, updated as the work evolves. A standalone Groundwork Assessment—Understand + Model + Decide—is a related but distinct entry point before major change.

When the project is done, the documentation travels with the codebase. Another engineer can get oriented faster because the knowledge isn’t locked in one person’s head. The client owns not just the software but a clearer record of how and why it works.

This is connected to the operation-first process, not separate from it. Building operation-first produces software that's worth capturing in writing. Building code-first produces software that's hard to document because the operational logic is scattered and implicit.

What to look for before you build

If you're evaluating help for a custom or modernization project—including work alongside a team you already have—the most important questions aren't only about technology. They're about how the work starts.

"How do you learn the operation before significant implementation?" A process that asks primarily about features and data tends to stay code-first. A process that asks primarily about workflow, rules, exceptions, and how things actually run today is building operation-first.

"What happens if you're not available six months after launch?" The answer should describe documentation — something that makes the system legible to another developer without you. Staying available is a business arrangement. Documentation is independence.

"Can you show me the specification process?" A developer who can show you a structured spec process — how operational understanding becomes a formal build plan — has built this practice into how they work. A developer who figures it out as they go builds faster at the start and surprises more often later.

The best custom software doesn't feel like software. It feels like the operation, formalized — the way your workflow actually runs, captured in a system that handles the cases that matter, including the ones nobody thought to mention explicitly.

That only happens if you start with the operation.