A named failure mode

Modular Mirage

Code that looks separated into clean modules — but is secretly bound together by assumptions no boundary actually enforces.

modular mirage (n.) — an architecture where the folder structure, type signatures, or file boundaries suggest independence between components, while the actual runtime behavior depends on shared, unstated assumptions the structure was never designed to hold.

Six boxes. One hidden shape.

This is what a generated codebase usually looks like on the surface — tidy, separated, each box doing its own job. Flip the switch to see what's actually connecting them underneath.

Surface view — six independent modules
Show hidden coupling
auth/boundary: clean
billing/boundary: clean
notify/boundary: clean
utils/boundary: clean
reports/boundary: clean
cache/boundary: clean

How you know it's there

You usually don't spot a modular mirage by reading the code. You spot it by watching what happens when someone touches one piece of it.

A short, familiar story

A team ships a checkout flow. The agent produces four clean-looking modules: cart/, pricing/, tax/, receipt/. Each has its own folder, its own types, its own tests. Code review takes ten minutes. It looks like good architecture.

Three weeks later: a fix to a rounding rule in tax/ silently changes the totals shown in receipt/. Nobody touched receipt/. Nobody reviewed it either.

The two modules were never actually independent. They were generated in the same session, against the same example numbers, and both quietly assumed prices round the same way. The folder structure said "separate." The behavior said otherwise. That gap is the mirage — and it's invisible until something moves.

Before you ask

Isn't this just technical debt?
Technical debt is usually a known shortcut — you can point to the corner that was cut. A modular mirage is different: nobody chose to couple these modules. The structure claims separation that was never actually built.
Isn't this just tight coupling?
Tight coupling is visible in the code — imports, shared globals, direct calls. A modular mirage hides in the gap between what the structure implies and what the runtime does. The code can look decoupled and still behave as one unit.
Why does this show up more with AI-generated code specifically?
A human writing five modules over five weeks makes five different sets of assumptions, and the mismatches surface early. An agent generating five modules in one session tends to reuse the same assumptions across all of them — so the coupling is consistent, quiet, and easy to miss in review.
How do you actually check for it?
Ask what happens if you delete a module, not what it imports. If nobody can answer in one sentence, the boundary is probably a mirage rather than a real seam.

Give it a name, and it gets easier to catch

If you've seen this pattern, it already has a name now. Share it so the next person doesn't have to explain it from scratch.