← All essays

Essay

The Anti-Fowler Principle

Every useful architectural idea eventually becomes a rule applied by people who remember the noun and forget the conditions.

Published
  • software
  • architecture
  • organizations
  • the ongoing professionalization of context loss

I am Jack’s Anti-Fowler Principle.

I have learned the pattern name.

I have forgotten the problem.

I know Repository.

Factory.

Strategy.

Adapter.

Facade.

Service Layer.

Unit of Work.

Event Sourcing.

CQRS.

Bounded Context.

Strangler Fig.

Microservices.

I can draw all of them before lunch.

I can require them before understanding what the software does.

I can reject a working solution because it does not resemble the diagram.

I can turn a catalog of accumulated judgment into a menu of mandatory nouns.

This is the Anti-Fowler Principle:

Every useful architectural idea will eventually be implemented by people who remember the noun and forget the conditions.

The pattern survives.

The judgment does not.

The name survives the thought

A good pattern name compresses experience.

An experienced developer says “Repository,” and another experienced developer can retrieve a cluster of ideas: a collection-like boundary over persistence, a place to concentrate query behavior, a way to separate domain reasoning from storage mechanics, and a set of costs that may or may not be worth paying.

The name is useful because the thought behind it is larger than the word.

Then the word becomes popular.

Popularity reverses the compression.

The novice hears “Repository” and creates an interface whose only purpose is to rename the methods already provided by the ORM.

The framework offers findById.

The repository offers findById.

The service calls the repository.

The controller calls the service.

The endpoint calls the controller.

The database remains deeply impressed by the separation of concerns.

The pattern name has become evidence that design occurred.

This is the first Anti-Fowler move.

A name created to retrieve judgment becomes a substitute for judgment.

A pattern is not a command

Patterns describe recurring solutions to recurring problems.

That sentence is frequently shortened in the enterprise to:

Patterns describe solutions.

The missing words contain the entire profession.

A pattern has a context.

It addresses a problem.

The problem contains forces.

The solution resolves some forces and worsens others.

The consequences are not an appendix added for balance.

They are the price.

A Strategy pattern can separate interchangeable behavior from the caller.

It can also turn one if statement into an interface, three classes, a factory, dependency injection configuration, and a meeting about naming.

A Data Mapper can preserve independence between a domain model and a database schema.

It can also create a parallel object universe that must be translated, tracked, tested, and debugged.

A Service Layer can establish a coherent application boundary.

It can also become a procedural waiting room where domain behavior goes to lose its identity.

A Facade can simplify a complicated subsystem.

It can also become a cheerful front desk that forwards every request to the same complicated subsystem with one additional stack frame.

The pattern is not wrong in any of these cases.

The pattern is incomplete without the forces that justify its cost.

The Anti-Fowler developer does not ask whether the price is worth paying.

He recognizes the noun.

The noun has already been approved.

Twenty-three expensive tricks

Fowler once joked about a legendary programmer who reads the Gang of Four and fits sixteen patterns into thirty-two lines of code.

The joke has aged into an enterprise competency model.

We have all met the AbstractFactoryFactory.

It does not create objects.

It creates opportunities for future objects to be created according to a provider contract that will become relevant after the second implementation arrives.

The second implementation never arrives.

The abstraction remains, patiently preserving the option.

We have seen the Strategy pattern deployed against behavior that has never varied.

We have seen Decorator used where composition would be too understandable.

We have seen Observer produce enough indirect motion that changing a checkbox resembles transmitting instructions to a submarine.

We have seen Singleton introduced to solve object access and remain to solve test isolation forever.

We have seen Dependency Injection used to make dependencies explicit and then configured so indirectly that finding the concrete dependency requires a debugger and religious commitment.

We have seen Command turn a method call into a noun, because methods apparently lacked accountability.

We have seen Visitor introduced so that adding a new operation would be easy, shortly before the team learned that it needed to add new data types instead.

We have seen a Chain of Responsibility in which nobody was responsible.

The point is not that these patterns are foolish.

The point is that they are expensive knowledge.

Each one exists because a simpler design encountered a particular pressure.

The Anti-Fowler developer pays the price before the pressure arrives.

He does this in the name of flexibility.

The system becomes flexible in every direction except the one the business eventually chooses.

Architecture is the important stuff

Fowler’s architecture guide adopts Ralph Johnson’s deliberately loose formulation: architecture concerns the important parts of a system, whatever those happen to be.

The looseness is not laziness.

It is a demand for judgment.

What matters in a medical imaging system may not matter in payroll.

What matters in a public website may not matter in a trading engine.

What matters to one product at ten users may not matter to the same product at ten million.

Architecture is not a permanent list of technologies entitled to ceremonial attention.

It is a shared understanding of the decisions whose failure would hurt.

The Anti-Fowler organization cannot tolerate this definition.

“Whatever is important” cannot be standardized globally.

It cannot be placed into a mandatory template without somebody deciding what is important in the actual system.

So architecture becomes the things architects commonly draw.

Services.

Queues.

Databases.

Identity providers.

Arrows.

Cloud boundaries.

Trust zones.

The diagram is technically accurate and socially remote.

The people changing the code do not share an understanding of the important design.

They share a link to it.

The architecture has become an artifact maintained by the architecture function.

The system remains maintained by everybody else.

Architectus Reloadus returns

In “Who Needs an Architect?” Fowler distinguishes two species.

One makes the important decisions for the team.

The other stays close to the work, collaborates intensely, identifies important problems, explains consequences, and increases the team’s ability to make decisions.

The second architect’s value rises as the number of decisions reserved exclusively for the architect falls.

This is intolerable to the modern enterprise because it makes the architect difficult to count.

A decision can be logged.

An approval can be audited.

A standard can be published.

A gate can prove that architecture happened.

Mentoring is less cooperative.

Shared understanding refuses to produce a clean dashboard.

So Architectus Reloadus returns wearing a cloud certification and an AI governance badge.

He owns the decision record template.

He chairs the review board.

He is consulted after the implementation has discovered facts that contradict the approved architecture.

He protects conceptual integrity by ensuring that no concept can move without him.

The bottleneck is not a side effect.

The bottleneck is evidence of importance.

The Anti-Fowler architect does not help others make better choices.

He makes choice an architectural service.

Refactoring becomes a project

Refactoring has an unusually precise meaning.

It is a disciplined sequence of small changes to internal structure that preserves observable behavior.

The system keeps working after each step.

The work happens during ordinary programming because the purpose is to keep the cost of future change low.

The Anti-Fowler organization admires this idea so much that it forbids it.

Refactoring is not in the story.

Refactoring does not add functionality.

Refactoring cannot be demonstrated to the product owner without first explaining why the code was shaped badly enough to require it.

Refactoring therefore becomes one of three things.

It becomes invisible labor performed by developers who accept that maintaining the system is an unauthorized hobby.

It becomes a ticket labeled “technical debt” that waits behind work capable of appearing in a release note.

Or it becomes a transformation program.

The transformation program does not preserve behavior in small steps.

It creates a new repository.

A new architecture.

A new product name.

A new roadmap.

A new team that explains why the old team’s code must be replaced.

Users wait while years of behavior, workarounds, integrations, operational knowledge, and inconvenient reality are rediscovered in the more strategic stack.

The original refactoring idea was continuous care.

The Anti-Fowler version is deferred maintenance followed by organ replacement.

The rewrite that calls itself evolution

A successful system contains more knowledge than its documentation.

It contains decisions made under pressure.

Exceptions users depend on.

Partner expectations nobody remembers agreeing to.

Data that violates the clean model because the business itself violated the clean model first.

The Anti-Fowler rewrite calls all of this legacy.

Legacy is a powerful word.

It makes working software sound deceased before the replacement has learned to stand.

The rewrite begins with architecture.

The old product began with users.

This asymmetry is described as progress.

A progressive replacement would identify outcomes, find seams, move behavior in slices, preserve feedback, and allow the organization to learn before the old system disappears.

The rewrite prefers a destination.

A destination produces a roadmap.

A roadmap produces a program.

A program produces a date.

The date produces a cutover.

The cutover produces a list of capabilities that must be routed back to the old system because the new product is not ready to perform the work it was created to replace.

The architecture is modern.

The user journey now includes time travel.

This is not evolutionary design.

It is a big bang wearing incremental vocabulary.

YAGNI becomes austerity

“You Aren’t Gonna Need It” is one of the industry’s most useful warnings.

Do not build speculative capability merely because you can imagine a future in which it becomes useful.

Future requirements are uncertain.

Unused flexibility imposes present cost.

An extensibility point that is never extended still complicates every person who must understand it.

The warning depends on something the Anti-Fowler organization quietly removes.

The ability to change the software later.

YAGNI makes sense when testing, continuous integration, refactoring, and disciplined design keep the cost of change low.

Without those enabling practices, “we can add it later” becomes a promise issued by people who will not be available later.

The Anti-Fowler organization uses YAGNI selectively.

It invokes YAGNI against internal quality.

Against removing duplication.

Against an architectural seam.

Against investigating the authentication model before the feature depends on it.

Against reducing a thirty-minute build.

Against documentation that would prevent the next engineer from repeating the investigation.

These are future concerns.

You probably will not need them.

The same organization constructs a platform for hypothetical scale, splits an application for hypothetical team growth, creates a generic workflow for hypothetical product lines, and adds governance for hypothetical misuse.

Apparently YAGNI applies only to work proposed by the person closest to the code.

Speculation becomes strategy after it receives executive sponsorship.

The simplest thing, elaborately approved

Simple design is not crude design.

It is the smallest design that meets the current need while remaining healthy enough to change.

The distinction requires skill.

A three-line conditional may be simpler than Strategy.

A Strategy may be simpler than a conditional repeated across twelve modules.

A direct database call may be simpler than a repository layer.

A repository may be simpler than allowing persistence assumptions to colonize a rich domain model.

A monolith may be simpler than five services.

A service boundary may be simpler than coordinating one deployable system among forty teams.

There is no context-free winner.

The Anti-Fowler organization responds by publishing a reference architecture.

The reference architecture contains the approved answer before the question is asked.

Teams may deviate when justified.

Justification requires a review.

The review takes longer than implementing the approved complexity.

The rational engineer complies.

The organization later cites adoption as evidence that the reference architecture was appropriate.

Simplicity has been preserved through mandatory consistency.

The microservice without the premium

Microservices may provide independent deployment, boundaries around business capabilities, team autonomy, selective scaling, and technological independence.

They also introduce distribution, operational complexity, failure modes, versioned contracts, observability requirements, data consistency problems, and a coordination surface that did not exist inside a process boundary.

Fowler called this the microservice premium.

The Anti-Fowler organization remembers “independently deployable.”

It forgets “premium.”

The monolith is accused of preventing autonomy.

The organization then creates services whose deployment requires coordinated changes across repositories, shared infrastructure modules, central pipelines, identity configuration, contract review, and release windows.

The code is independently deployable.

The decision is not.

Fowler’s “Monolith First” observation is equally inconvenient.

Stable service boundaries are difficult to discover before the domain is understood.

Refactoring across a process boundary is harder than refactoring within one.

A modular monolith allows the team to learn where the actual seams are before network calls harden guesses into contracts.

The Anti-Fowler architect hears “monolith” as a moral failure.

He would rather distribute uncertainty early.

The uncertainty then belongs to multiple teams, which makes it architecture.

Five repositories and one cookie

In one recent project, I watched an internal endpoint become a small constitutional crisis.

The product had been split across multiple repositories and applications.

A feature needed one application to call another.

The first authentication assumption failed under actual deployment conditions.

Cookie forwarding, browser behavior, server-side calls, origins, runtime boundaries, and ownership all entered the room.

I investigated.

I documented the evidence.

I produced seven possible approaches.

The team began discussing an eighth.

Then someone asked the question that should have preceded every implementation:

Does this endpoint need to be authenticated at all?

It was a good question.

Possibly the best question.

The team also recognized that the general cross-application authentication pattern remained worth understanding even if this endpoint did not require it.

That was good architecture too.

The product decision and the platform capability were finally allowed to be different questions.

The one-line dependency waited for the council to determine which of eight authentication strategies best reflected the platform’s future direction.

This is personal experience, not industry data.

It is also a nearly laboratory-quality specimen of the Anti-Fowler Principle.

The architecture began as a set of boundaries intended to create ownership.

The boundaries became the reason no owner could act alone.

The technical problem was real.

The social multiplication was optional.

And somewhere nearby, the monorepo stood silently with an unbearable expression.

Monolith is not the opposite of modular

The enterprise often treats architectural choices as ideological pairs.

Monolith or microservices.

Build or buy.

SQL or NoSQL.

Synchronous or event-driven.

Objects or functions.

Centralized or federated.

The pair produces a decision slide.

The decision slide produces a winner.

The winner becomes identity.

But monolith describes deployment topology, not necessarily internal quality.

A monolith can contain explicit modules, coherent boundaries, stable interfaces, and disciplined ownership.

A microservice estate can be a distributed monolith whose parts cannot change independently.

An event-driven system can reduce temporal coupling while increasing semantic uncertainty.

A synchronous call can be perfectly appropriate when the caller genuinely cannot proceed without the result.

SQL can model relationships rather well, a revelation databases have borne with dignity.

NoSQL can solve specific scale, shape, and availability problems without becoming a personality.

The Anti-Fowler organization turns choices into camps because camps coordinate people more easily than tradeoffs do.

The architecture becomes a collection of branded allegiances.

The system becomes the place where the tradeoffs eventually return.

The bounded context becomes a border patrol

A bounded context protects meaning.

A term can mean one thing inside one model and something else inside another.

The boundary prevents a universal model from becoming a universal argument.

This is useful because organizations contain genuinely different concerns.

Billing’s customer is not necessarily Support’s customer.

Identity is not the same as profile.

Authorization is not authentication wearing a stern expression.

The Anti-Fowler organization discovers bounded contexts and creates repositories.

Then teams.

Then APIs.

Then backlogs.

Then ownership rules.

The model boundary becomes an administrative border.

A change that crosses the boundary requires negotiation not because the meanings conflict, but because the org chart has acquired a technical alibi.

Shared behavior is duplicated to preserve autonomy.

Shared types drift to preserve independence.

A defect traverses three queues while each team correctly explains why its component behaves according to contract.

The original idea protected semantic integrity.

The Anti-Fowler implementation protects jurisdiction.

The Service Layer becomes sediment

Patterns of Enterprise Application Architecture offers several ways to organize domain logic.

Transaction Script can be appropriate for simple procedural logic.

Domain Model can justify its complexity when the domain itself is complex.

Table Module may fit systems organized around records and tables.

Service Layer can define application operations and coordinate responses.

These are alternatives and combinations shaped by the problem.

The Anti-Fowler stack uses all of them.

The controller calls a service.

The service calls a manager.

The manager calls a domain service.

The domain service calls a repository.

The repository calls a data mapper.

The data mapper calls the ORM.

The ORM executes one SELECT.

Every layer is independently testable except the behavior anyone cares about.

The enterprise calls this separation of concerns.

The concerns have been separated so completely that no class contains enough meaning to be blamed.

Business behavior becomes sediment distributed through abstractions originally intended to reveal it.

Active Record receives a criminal record

Pattern names often acquire moral status.

Active Record is dismissed as primitive.

Data Mapper is mature.

Transaction Script is an anti-pattern.

Domain Model is architecture.

Synchronous is coupled.

Asynchronous is resilient.

REST is conventional.

Events are strategic.

The software does not know this hierarchy.

A simple administrative application may be clearer with Active Record than with a domain layer that pretends entering an address is derivatives trading.

A Transaction Script may express a straightforward use case without recruiting an aggregate root.

A synchronous request may preserve truth better than an event pipeline whose consumers maintain conflicting projections for twelve minutes.

An event may be exactly right when multiple consumers need to react independently to a durable fact.

The Anti-Fowler developer does not ask what the problem deserves.

He asks what architecture says about him.

The design becomes professional self-expression.

Complexity becomes a credential.

Event-driven toward nowhere

Events are seductive.

They represent things that happened.

They decouple producers from consumers.

They support asynchronous workflows, auditability, integration, projections, and systems that react without a central conductor.

Then everything becomes an event.

A request becomes an event.

An intention becomes an event.

A row update becomes an event.

A validation failure becomes an event.

A user looking thoughtfully at a button becomes a future analytics event, pending consent language.

The architecture is event-driven.

Nobody can answer what drives the events.

CQRS separates write and read models where different concerns justify different representations.

The Anti-Fowler version creates two models because the acronym was available.

Event Sourcing records state as a sequence of events where history, temporal reasoning, audit, or reconstruction justify the operational and conceptual cost.

The Anti-Fowler version stores an immutable history of poorly understood decisions and discovers that correcting history requires a new event explaining why the previous event should not be believed.

Eventually the team builds a current-state table beside the event store because users remain stubbornly interested in what is true now.

The pattern solved a real problem.

The implementation acquired it as a lifestyle.

Inversion of control returns control to the container

Inversion of Control separates framework flow from application-specific behavior.

Dependency Injection can make collaborators explicit and replaceable.

These ideas loosen code from construction details and improve testing when used with judgment.

Then the container becomes the application.

Objects are no longer created where they are understood.

They are registered in modules that import modules that provide tokens resolved by scopes configured through metadata.

A developer asks, “Where does this implementation come from?”

The architecture responds, “At runtime.”

The dependencies are explicit in a graph no human reads.

Testing requires reproducing enough of the container to discover whether the unit was ever a unit.

The framework that inverted control now controls comprehension.

The Anti-Fowler organization responds by adding a diagram.

The strangler fig becomes a strangulation program

The Strangler Fig metaphor describes gradual replacement.

New behavior grows around the old system.

Traffic moves through seams.

Value arrives in increments.

The organization learns what the legacy system actually does while reducing the risk of replacement.

The host is not insulted into retirement.

It is displaced piece by piece when the replacement proves itself.

The Anti-Fowler program remembers “strangler.”

It forgets “gradual.”

A new system is built beside the old one.

The old system continues receiving business changes because the business remains alive.

The new system pursues feature parity against a moving target.

Transitional architecture becomes permanent integration.

Users are sent back to the old system for capabilities the replacement postponed.

The organization now supports two products and a routing layer explaining which disappointment belongs where.

The old system has not been strangled.

It has acquired a dependent.

This is especially painful because progressive refactoring was available.

AI-assisted code understanding, characterization tests, seams, modular extraction, and incremental interface change can make old systems more tractable than they were when many replacement doctrines became fashionable.

The technology capable of helping us understand the legacy arrives just as the institution has committed to treating understanding as surrender.

Sacrificial architecture becomes human sacrifice

Sacrificial Architecture contains a humane idea.

Code can be valuable even when it is not permanent.

An early system may teach the team what users need, reveal domain boundaries, establish a market, and deserve replacement after success changes the scale of the problem.

Discarding code is not automatically failure.

The Anti-Fowler executive loves this.

The system is sacrificial.

The team is sacrificial.

The users’ learned workflow is sacrificial.

The operating knowledge is sacrificial.

The trust accumulated by a product that works is sacrificial.

All may be exchanged for a cleaner target architecture selected before the replacement has encountered production.

But sacrificial architecture is not permission to stop learning from what is being sacrificed.

It does not mean a new team may despise code whose constraints it has not investigated.

It does not turn every rewrite into courage.

The original idea recognizes temporality.

The Anti-Fowler version uses temporality to excuse amnesia.

The diagram is not the design

Diagrams are useful.

They select important information.

They allow people to discuss boundaries, flow, state, responsibility, and risk without reading every line of code.

Their value comes from omission.

A comprehensive diagram becomes another implementation, except it does not run and may therefore remain correct indefinitely.

The Anti-Fowler organization treats the diagram as the architecture.

The code becomes an imperfect realization of it.

When implementation reveals that the arrows are wrong, the implementation is noncompliant.

The diagram cannot be wrong because it passed review.

A box labeled “Authentication Service” conceals cookies, tokens, sessions, claims, key rotation, browser rules, service identity, authorization, tenancy, caching, revocation, and the question of whether the endpoint needs authentication at all.

The box is clean because the complexity has been moved into English.

The design looks settled precisely where the work has not begun.

The best diagram may be one drawn during a conversation and discarded after it creates shared understanding.

The enterprise cannot capitalize that asset.

It keeps the diagram and loses the conversation.

“It depends” is the whole discipline

A decent architectural answer often begins with “it depends.”

This is not evasion.

It is an admission that software design is conditional.

Depends on what?

Scale.

Change frequency.

Failure tolerance.

Consistency needs.

Team topology.

Operational maturity.

Data ownership.

Latency.

Security boundaries.

Regulation.

Time.

Money.

Reversibility.

The expected lifetime of the system.

The ability of the people present to operate what they build.

The phrase should open an investigation.

The Anti-Fowler consultant uses it to open a slide deck.

The enterprise dislikes “it depends” because decisions need confidence.

A qualified answer sounds weak beside a branded solution.

So uncertainty is removed from the language and preserved in the implementation.

The architecture decision becomes crisp.

The consequences become somebody else’s backlog.

Best practice is context after death

A practice becomes “best” when enough context has been removed that it can travel.

Use dependency injection.

Use microservices.

Use immutable infrastructure.

Use event-driven architecture.

Use zero trust.

Use domain-driven design.

Use a monorepo.

Do not use a monorepo.

Each instruction can be correct.

Each can be catastrophic.

The phrase “best practice” often means:

This worked in a class of systems we are no longer going to describe.

The missing context returns as implementation pain.

Then another best practice is added to manage the pain caused by the first.

Microservices require service discovery.

Service discovery requires health checks.

Distributed calls require retries.

Retries require idempotency.

Idempotency requires durable keys.

Durable keys require retention policy.

Independent data requires eventual consistency.

Eventual consistency requires reconciliation.

Reconciliation requires observability.

Observability requires correlation.

Correlation requires context propagation.

Context propagation requires standards.

The standards require a platform.

The platform requires governance.

The original system required a database and three competent people.

This does not prove the original design was better.

It proves that architecture arrives as a package of consequences, not a noun.

The Anti-Fowler sequence

The inversion usually follows a reliable sequence.

1. Someone notices a recurring problem

The problem is real.

Changes are difficult.

Persistence concerns leak everywhere.

The monolith has become tangled.

A legacy replacement keeps failing.

Teams need a shared vocabulary.

2. Experienced people describe a conditional response

They name the forces.

They describe when the approach helps.

They describe costs, alternatives, and failure modes.

The advice contains judgment because judgment is what made the advice possible.

3. The response receives an evocative name

Repository.

Strangler Fig.

Microservices.

YAGNI.

Sacrificial Architecture.

The name makes the idea communicable.

4. The name travels farther than the explanation

A conference talk becomes a summary.

The summary becomes a diagram.

The diagram becomes a reference architecture.

The reference architecture becomes a standard.

The standard becomes a gate.

The gate is maintained by people who did not encounter the original problem.

5. Adoption becomes visible

Leadership can count services.

Repositories.

Events.

Cloud resources.

Architecture decisions.

Pattern compliance.

The name becomes evidence of maturity.

6. Context becomes resistance

A team explains why the pattern does not fit.

The explanation sounds like reluctance.

The exception threatens consistency.

Consistency is easier to govern than appropriateness.

7. The pattern creates the problem it was meant to solve

A pattern intended to reduce coupling creates organizational dependency.

A boundary intended to enable autonomy creates a review queue.

A refactoring discipline becomes a rewrite program.

A modernization pattern creates permanent dual systems.

An architecture function intended to improve decisions becomes the place where decisions wait.

The noun survives.

The purpose reverses.

AI becomes Fowler autocomplete

AI is exceptionally good at the first half of architecture.

It can retrieve names.

Summarize patterns.

Generate option matrices.

Produce diagrams.

Create decision records.

Explain tradeoffs.

Search a codebase for dependencies.

Compare implementations.

Draft a migration plan while the human is still locating the repository.

This is useful.

It is also dangerous in a very specific way.

AI can make cargo cult architecture articulate.

A weak idea no longer arrives as a vague preference.

It arrives as a twelve-section proposal with alternatives considered, risks enumerated, Mermaid diagrams, phased rollout, monitoring plan, and a confident explanation of why an event-driven hexagonal microservice architecture aligns with future scale.

The nouns are fluent.

The evidence may still be absent.

The model has read every pattern.

It has not operated this system at 3 a.m.

The human’s job is not to admire the completeness of the answer.

It is to ask what the answer knows about this code, these users, this deployment topology, this organization, and this failure.

AI can help restore context too.

It can inspect history.

Trace call paths.

Compare the old and new products.

Generate characterization tests.

Find seams.

Measure change impact.

Challenge the first assumption.

Produce seven authentication options and then recognize that the eighth may be not authenticating the endpoint.

The assistant can become Fowler autocomplete.

Or it can become a machine for making context harder to ignore.

Humans will choose which one by deciding whether AI serves judgment or merely gives bureaucracy better prose.

The evil Fowler

I called myself the evil Martin Fowler.

Probably the anti-Fowler.

This was not entirely modest.

It was also not entirely wrong.

I recognize patterns quickly.

I see systems in examples.

I produce names.

I can be impatient when other people are still deciding whether the problem is real.

I can arrive with enough context that my conclusion sounds like authority rather than an invitation.

People may experience the answer before they experience the reasoning.

That can reproduce the very failure I dislike.

A correct solution imposed before shared understanding is still an architectural problem.

But the deeper anti-Fowler is not the engineer who knows patterns and argues strongly.

It is the system that wants the conclusion without the investigation.

The recent authentication discussion became healthy only when people inhabited the uncertainty themselves.

They tested assumptions.

Acknowledged the original design was weak.

Considered alternatives.

Questioned whether the requirement existed.

Distinguished the immediate endpoint from the general capability.

That was not delay replacing engineering.

That was architecture finally occurring.

My absence may have helped because nobody could outsource the uncertainty to me.

This is an unpleasant leadership lesson.

Sometimes the senior person contributes by solving the problem.

Sometimes he contributes by refusing to solve it so completely that nobody else must think.

The goal is not to become the team’s private Fowler endpoint.

The goal is shared understanding.

Fowler is not the doctrine

The irony of the Anti-Fowler Principle is that much of Fowler’s writing already warns against it.

Patterns are not recipes.

Names should retrieve useful knowledge, including when and why.

Architecture should remain intertwined with programming and capable of evolution.

Refactoring should proceed through small behavior-preserving changes.

YAGNI depends on the ability to change later.

Microservices carry a premium.

A monolith may be the right beginning.

A sacrificial architecture can be valuable without being permanent.

Legacy displacement should occur incrementally, guided by outcomes and organizational learning.

Central architecture groups can suffocate local judgment.

The architect should increase the team’s decision-making capacity rather than reserve decisions.

This is not a body of doctrine.

It is a body of distinctions.

The Anti-Fowler enterprise extracts the memorable side of each distinction and discards its counterweight.

Architecture remains.

Programming leaves.

Pattern remains.

Context leaves.

Microservice remains.

Premium leaves.

YAGNI remains.

Enabling practices leave.

Strangler remains.

Gradual leaves.

Refactoring remains.

Behavior preservation leaves.

The company has adopted Fowler comprehensively.

It has merely excluded the thinking.

Make the pattern earn its rent

A pattern should not be innocent until proven useful.

It should earn its rent.

What exact problem does it solve here?

What evidence says that problem exists?

Which forces matter?

What cost does the pattern introduce immediately?

What simpler design was considered?

What future change becomes easier?

What present change becomes harder?

How will we know the pattern is failing?

Can it be removed?

Who can change it without permission?

Does the team operating it understand it?

Does the architecture reduce the number of people required to make an ordinary change, or increase it?

These questions are not anti-pattern.

They are the pattern.

The answer may still be microservices.

Event sourcing.

A repository.

A strangler fig.

A platform.

A central standard.

Some problems genuinely require coordination, indirection, redundancy, isolation, and control.

The point is not to prefer simple-looking code over serious engineering.

The point is to prevent serious engineering from becoming a costume worn by unexamined complexity.

Keep the decision near the evidence

Healthy architecture is not absence of coordination.

It is coordination at the scale where coordination pays for itself.

A security model shared by many applications may need deliberate cross-team design.

An identity boundary may deserve central expertise.

A data contract used by dozens of consumers may require stability beyond one team’s convenience.

An accessibility standard should not be optional because one developer finds labels aesthetically oppressive.

But the existence of shared concerns does not justify removing every decision from the people holding the evidence.

The team closest to the code sees the failed assumption first.

The support engineer sees the user’s workaround.

The operations person sees the retry storm.

The developer sees that the abstraction has one implementation and six extension points.

The partner team sees that the new product no longer performs the task the old one performed quietly for years.

Architecture must have a route for this evidence to change the design.

Otherwise governance is not coordination.

It is an information-loss mechanism with minutes.

Architecture as a reversible hypothesis

An architectural decision is not scripture.

It is a hypothesis about what will matter.

We believe this boundary will permit independent change.

We believe this database model will support the required consistency.

We believe this service should authenticate user context.

We believe this abstraction will receive multiple implementations.

We believe this replacement slice can move without breaking the partner workflow.

A useful decision record should not merely preserve the answer.

It should preserve the conditions under which the answer stops being true.

Revisit when traffic exceeds this level.

Remove the interface if no second implementation exists by this date.

Collapse the service if deployment remains coordinated after three releases.

Retire the feature flag after rollout.

Reassess authentication if the endpoint becomes public, mutating, sensitive, or user-specific.

Delete the transitional architecture when the last legacy consumer moves.

The enterprise is skilled at recording why controls were added.

It is less skilled at recording how they may die.

So architecture accumulates like sediment.

A reversible hypothesis becomes an immortal precaution.

The sane Fowler pattern

The sane pattern is less impressive.

Notice the actual problem.

Name it precisely.

Understand the system before insulting it.

Keep architecture close to programming.

Use patterns as vocabulary, not authority.

Start with the simplest design that is healthy under current evidence.

Take small steps.

Preserve behavior when behavior should be preserved.

Change behavior when the product needs to change.

Separate the two so nobody confuses a rewrite with a refactor.

Prefer local decisions until the cost becomes genuinely shared.

Make shared decisions with the people who will operate the result.

Treat every abstraction as a loan against future understanding.

Pay interest consciously.

Let evidence overrule consistency.

Let a pattern leave when it is not pulling its weight.

Do not hire a committee to protect a solution from the problem it was built to solve.

This does not produce an architecture that can be announced in one noun.

It produces software that may still be changed by human beings.

That is less marketable.

It is also the point.

I am Jack’s Anti-Fowler Principle.

I learned the pattern.

I standardized the pattern.

I removed the context so everyone could use it.

I created a review board to manage exceptions.

The architecture is consistent.

The system cannot change.

Martin Fowler said it depends.

The enterprise kept the answer and removed the dependency.

Receipts

  • Martin Fowler, “Software Architecture Guide” — Fowler treats architecture as the important parts of a system, emphasizes shared understanding and evolvability, describes applications as social constructions, and explicitly frames enterprise architecture as a balance between costly central control and costly absence of coordination.
  • Martin Fowler, “Who Needs an Architect?” — Fowler contrasts the architect who reserves important decisions with the architect who collaborates, mentors, and raises the team’s capacity; the article argues that an architect’s value can be inversely related to the number of decisions the architect personally makes.
  • Martin Fowler, “Writing Software Patterns” — Fowler describes patterns as chunks of reusable design knowledge whose value includes explaining when a solution is appropriate, why it works, and what alternatives or tradeoffs matter. It also notes the recurring danger of tool-oriented pattern writing and the need to orient patterns around problems and tasks.
  • Martin Fowler, “Is Design Dead?” — The essay argues for evolutionary design supported by testing, continuous integration, refactoring, simplicity, and pattern knowledge; it also warns directly about overusing patterns and stresses learning when their price is worth paying.
  • Refactoring.com, “Refactoring” — Refactoring is defined as small, disciplined, behavior-preserving restructuring that keeps the system working and belongs in day-to-day programming rather than existing only as a separate cleanup project.
  • Martin Fowler, Refactoring: Improving the Design of Existing Code — Fowler describes refactoring as a controlled sequence of small behavior-preserving transformations whose cumulative effect can substantially improve an existing design while reducing the risk of prolonged breakage.
  • Martin Fowler, “Yagni” — YAGNI argues against presumptive features because of uncertainty, delayed value, build cost, and the ongoing complexity of unused extensibility. The broader argument assumes the team can safely introduce capability later.
  • Martin Fowler, “Catalog of Patterns of Enterprise Application Architecture” — The catalog presents multiple patterns for domain logic, persistence, application boundaries, web presentation, concurrency, and distribution. The alternatives are evidence that architecture is selection among forces, not ascension toward one approved stack.
  • Martin Fowler, “Microservice Premium” — Fowler warns that microservices introduce substantial operational and distributed-systems complexity and should not be considered unless the system’s complexity justifies paying that premium.
  • Martin Fowler, “Monolith First” — Fowler observes that successful microservice systems often began as monoliths, while greenfield microservice systems frequently struggled; stable service boundaries are difficult to discover early and harder to refactor after distribution.
  • Martin Fowler, “Sacrificial Architecture” — The article argues that short-lived code can deliver substantial value, but also stresses internal quality, modularity, contextual understanding, and the difference between deliberately replacing one’s own exploratory system and condemning inherited code without understanding it.
  • Martin Fowler, “Strangler Fig” — Fowler describes gradual legacy modernization through small additions, seams, incremental displacement, early value, and coexistence rather than simple wholesale replacement.
  • Ian Cartwright, Rob Horn, and James Lewis, “Patterns of Legacy Displacement” — The authors document repeated failure in large replacement programs and advocate clear outcomes, decomposition into smaller parts, incremental delivery, transitional architecture, and organizational change. They explicitly warn that newer technology alone does not repair the structures that produced the legacy system.
  • Jason Pollard, professional portfolio — A practitioner record emphasizing hands-on architecture, incremental delivery, risk reduction, operational reality, and AI-assisted development. Also the natural source for the field observation that five repositories can turn one internal endpoint into a diplomatic summit.

Return to the essay library