For almost two decades, I built systems the way the industry taught us to build them.

Layered architectures. CQRS. MediatR pipelines. Repositories over ORMs. DTO mapping layers. Service abstractions over abstractions.

And to be fair, none of those ideas appeared by accident.

They solved real problems: organizational scaling, testability, onboarding, operational consistency, and long-term maintainability. When you operate dozens of services across multiple teams, consistency becomes a force multiplier. A familiar structure reduces cognitive load. A common operational contract makes troubleshooting predictable.

A microservice template from 2018 may look architecturally outdated today, but operationally it can still be extremely mature.

And that matters.

But somewhere along the way, many of us started building architecture not because the system required it, but because the template expected it.

The result was often a familiar “enterprise layer cake”:

Controller
  → MediatR
    → Handler
      → Service
        → Repository
          → ORM
            → Database

Perfectly structured. Perfectly abstracted. And increasingly disconnected from the actual complexity of the business problem.

Over time, I started noticing that many abstractions were no longer reducing complexity — they were redistributing it.

The interesting part is that this became much harder to ignore in ecosystems like Rust.

Rust tends to punish decorative abstraction. Ownership, error propagation, concurrency boundaries, and runtime behavior remain highly visible. Complexity becomes harder to hide behind architectural layers alone.

After spending enough time in that environment, returning to heavily ceremonial enterprise templates started feeling increasingly difficult to justify.

Not because abstraction itself is bad.

But because unnecessary abstraction rarely removes complexity. More often, it distributes it across hidden control flow, debugging friction, operational ambiguity, and cognitive overhead that compounds over time.

At the same time, the industry itself has shifted.

Modern engineering organizations increasingly optimize for speed, iteration, product-market fit, and delivery velocity. AI accelerated this trend even further.

Large amounts of boilerplate can now be generated almost instantly. CRUD code became cheap. Scaffolding became trivial.

But code generation has an interesting side effect: it changes what becomes expensive.

Working code is cheaper than ever. Reasoning about systems is not.

AI can generate working implementations remarkably fast.

It can also generate working chaos remarkably fast.

And that is why I believe we are not abandoning architecture.

We are abandoning ceremonial architecture.

The industry is slowly rediscovering something simpler: good engineering is not measured by the number of patterns applied, but by the clarity of the resulting system.

Sometimes the difference is surprisingly small.

A service does not necessarily become cleaner because every request passes through:

Controller → Mediator → Handler → Service → Repository

In many cases, a more direct and explicit flow is operationally easier to reason about:

Endpoint → Domain Logic → Database

The goal is not minimizing layers at all costs.

The goal is ensuring that every layer carries its own operational or cognitive justification.

This is especially visible in large microservice environments.

When you have 50+ services, standardization still matters enormously:

  • telemetry,
  • authentication,
  • deployment conventions,
  • tracing,
  • resiliency,
  • security defaults,
  • operational tooling.

Those things benefit from consistency.

But internal service complexity often does not.

A simpler programming model with a stable operational contract is frequently a better trade-off than endlessly reproducing enterprise ceremony.

This is also why many experienced engineers are increasingly drawn toward ecosystems that emphasize explicitness over abstraction-heavy frameworks.

Not because engineering discipline stopped mattering.

But because many of us spent years learning where engineering actually creates value — and where it merely reproduces organizational folklore.

The future probably does not belong either to massive enterprise abstraction layers or to chaotic “just ship it” development.

It belongs to systems that remain understandable under change.

Because in the end, software engineering is not only about how fast we can generate code.

It is about how long we can still reason about the systems we generate.