Skip to content

Fractal Architecture

aka: the same view at every zoom level

Every zoom level - method, class, slice, module, system - fits in your head on its own. That is what keeps cognitive load low.

The rules for drawing boundaries don't change when you zoom in or out.

Fractal architecture is a design lens, not an architecture style: the structure looks self-similar at every zoom level, so only one level has to fit in your head at a time. Working memory holds just a few things at once - keeping each level small is what keeps cognitive load manageable.

The same layout repeats at every level. A feature (vertical slice):

📁 orders
    📁 verifying-order
    📁 confirming-order
    📁 registering-order
    📁 order-storage   // technical detail, kept local

Zoom out - modules and the system look the same:

📁 erp
    📁 e-commerce
        📁 shopping-carts
        📁 orders
    📁 marketing
    📁 sales

Zoom in - a single feature decomposes the same way:

📁 verifying-order
    📁 anti-fraud-detection
    📁 high-value-customer-verification
    📁 external-order-verification

Each level declares what it needs and what it exposes, and hides the rest - so it is understandable without opening the level nested inside it. When that fails, the level is doing too much.

Why

  • Lower cost of change - a change stays inside its level, so refactoring is safe and side effects are bounded.
  • One mental model - the same boundary rules apply at every scale, so there is less to learn and decisions stay local.
  • Grows with complexity - depth is added only when a level earns it, avoiding up-front boilerplate (Onion pays it early).
  • Cheaper to read - only one level is in mind at a time; code is read far more often than written.

When

  • Use for most code where readability and change-cost matter - fits naturally with Vertical Slice and Lightweight.
  • Skip / go easy for trivial or throwaway code, where the repeated shape is pure overhead.
  • Doesn't solve cross-cutting concerns (transactions, security) or where boundaries belong - domain modelling still decides that.

How to apply

  1. Keep every level graspable - a method, class, slice, or service fits in one mind at once (~5-9 chunks, one screen). Too much? Split. Adds nothing? Collapse.
  2. Use the same rules at every scale - related things together, unrelated apart, dependencies pointing inward - from method to service.
  3. Add depth only when needed - start flat; nest a new level only when the current one stops being graspable. Fractal ≠ layers everywhere.

Smell test

  • Understanding one feature requires opening three nested boxes → levels aren't graspable (rule 1).
  • A class follows different structural rules than the slice around it → mixed mental models (rule 2).
  • Layers exist "because the architecture says so", not because a level got too big → premature depth (rule 3).

In C#

The same in → logic → out shape appears at the slice level and again inside the aggregate it calls - the structure is identical when zooming in.

// Zoom level: slice (feature)
public static class ApproveOrder
{
    public record Command(Guid OrderId, string ApprovedBy);
    public record Result(OrderStatus Status);

    public static Result Handle(Command command, IOrderStore store)
    {
        var order = store.Load(command.OrderId);   // in
        order.Approve(command.ApprovedBy);         // logic
        store.Save(order);
        return new Result(order.Status);           // out
    }
}

// Zoom level: class (aggregate) - same shape
public sealed class Order
{
    public OrderStatus Status { get; private set; }

    public void Approve(string approvedBy)         // in
    {
        if (Status != OrderStatus.Pending)         // logic (guard)
            throw new InvalidOperationException("Only pending orders can be approved.");

        Status = OrderStatus.Approved;             // out (state change)
    }
}

Background

The term and its champions, in one line each:

  • Mark Seemann - code should be self-similar: comparable amount of detail at every zoom level.
  • Vlad Khononov - the same coupling/cohesion trade-offs recur at every scale.
  • Oskar Dudycz - compose the same simple patterns (slices, handlers) instead of heavy layering.