> ## Content Index
> Fetch the complete content index at: https://ghostbabble.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# We've Confused Complexity With Sophistication
- URL: https://ghostbabble.com/complexity-with-sophistication/
- Published: 2026-11-01T14:01:47.000Z
- Updated: 2026-11-03T11:52:33.000Z
- Description: Why each architectural component needs a concrete requirement, an operating owner and a recoverable failure path.
- Author: Ghost X

There is a point in an architecture discussion where the solution starts accumulating components faster than the problem is getting explained. A queue appears. Then a cache. Then another service to coordinate the queue and cache.

Every component may have a reasonable purpose. I still want to know whether the original problem requires all of them.

An architecture diagram is very good at showing that we know the names of things. It is less good at showing who will operate those things after the people in the meeting move on.

## Every box becomes somebody's responsibility

A new service needs deployment, access control, monitoring, backup decisions, and a way to recover when it fails. A dependency brings assumptions about latency, availability, and change. Those costs can be justified. They belong in the design discussion.

Suppose a diagram adds a queue between two small services. What happens when the consumer stops? How will somebody distinguish a delayed message from a lost one? Can the same work arrive twice? How does a bad message stop blocking useful work? Who can inspect the backlog without gaining unnecessary access to the payload?

Those are design questions the new component introduces. Buying a managed queue may remove some infrastructure work, but it doesn't decide what the application should do with a repeated request.

The component that took an afternoon to add can remain somebody's responsibility for years. If its operating cost disappears into a central support queue, the original design can look much cheaper than it actually is. That is one way [recurring recovery becomes somebody else's workload](https://ghostbabble.com/sre-janitorial-department/).

## Start with the constraint you actually have

Consider a hypothetical application that needs to produce one report every evening. The report takes a few minutes, reads a known dataset, and can finish before the next business day.

Before choosing a scheduler, queue and worker fleet, write down what matters. What is the latest acceptable completion time? Can two runs overlap? What evidence records a completed report? What happens if the machine restarts halfway through? Is repeating the calculation harmless, or could it send the same result twice?

A small scheduled process with durable run records and a useful failure notification might satisfy those requirements. It might also fail them. A single host could be an unacceptable point of failure. The input volume might be about to exceed the available processing window. The report could depend on a downstream service that needs controlled backpressure.

Now there is something concrete to discuss. Add the component that addresses the actual constraint, and explain how to know whether it works. The queue has a reason to exist beyond looking familiar in a reference architecture.

An expected future workload deserves a migration plan. It doesn't automatically deserve all of that future workload's machinery today.

## Simplicity needs evidence too

A single script with undocumented state and broad credentials can be harder to operate safely than a well-designed service. Counting boxes is a poor substitute for examining behavior.

I would ask another engineer to walk through an ordinary run, a partial failure, and a change to one requirement. Where does state live? Which step can be repeated? Which credentials are needed? What identifies the version that ran? What would tell an operator to stop rather than try again?

If those answers depend on finding the original author, the design is carrying hidden complexity. Moving the code into one file has not removed it.

The same applies to a large shared automation job. A single entry point with twenty unrelated modes can be more difficult to understand than several narrowly scoped jobs. [Separating a pipeline's responsibilities](https://ghostbabble.com/one-pipeline-one-job/) is useful when it also separates permissions, history and change risk. Renaming the files while keeping every dependency coupled accomplishes much less.

## Make the cost of a choice visible

An architecture review can be more useful if each proposed component has a short explanation beside it: the requirement it satisfies, the failure it introduces, its owner, and the evidence that would justify changing it.

For a cache, that might include an observed latency problem, an acceptable age for the data, and the behavior when the cache is unavailable. For a separate service, it might include an independently changing responsibility and a deployment boundary the team can actually maintain. These explanations can be brief. Their value is that somebody can question the choice without debating whether the technology is sophisticated enough.

It also helps to name a removal condition. If the throughput assumption changes, does the extra worker pool still make sense? If nobody uses a coordination layer except one caller, is the boundary still useful? Components are easier to add than retire when their original purpose was never recorded.

I like a design that can explain why each piece exists. If removing a piece makes no meaningful requirement harder to satisfy, we should at least consider removing it. The next person operating the system should be able to follow that reasoning from the evidence, rather than reconstruct it from the diagram.