Utilitarian Architecture

Utilitarian Architecture for Laravel

Utilitarian Architecture is an approach to application architecture that prioritizes usefulness, clarity, and real-world outcomes over theoretical purity. It values clean code and good design principles, but treats them as tools — not goals.

Decisions are made based on their practical impact on the system, the team, and the problem being solved. Patterns, abstractions, and layers are applied consciously, only when they increase overall utility.

Core Idea

What matters is not how elegant a structure looks, but how useful it is in practice.

Architecture is a means of achieving outcomes.

Software is an implementation detail.

1

Use Case as the Core of the System

The basic unit of the architecture is a business operation, not a layer or a technical pattern.

Command — an atomic write operation.

Query — a read scenario.

Action — orchestration and application logic: calculations, transformations, conditions, and coordination of commands and queries.

Command, Query, and Action are not required together — each is used only when it makes sense for the task at hand.

2

Soft CQRS as a Convention

Read and write responsibilities are separated intentionally, but without turning CQRS into an architectural framework.

  • • no mandatory interfaces
  • • no enforced DTOs or return formats
  • • no infrastructure-level CQRS

Command / Query / Action are clear conventions that improve readability and predictability, while still allowing each problem to be solved in the most reasonable way.

3

Freedom of Tooling Inside a Use Case

The architecture does not fix the technical level at which a problem must be solved.

Inside commands, queries, and actions, it is acceptable to work with Eloquent, use the Query Builder, call external APIs, use SQL, HTTP, SDKs, file systems, or any other appropriate tools.

What matters is not how the task is implemented, but where it is defined and which business meaning it expresses. A use case is a responsibility boundary, not an abstraction layer.

4

Tooling-First Approach

Utilitarian Architecture requires nothing by default.

Value Objects, DTOs, notifications, lightweight helpers, and custom utilities are not architectural obligations, but ready-to-use tools for frequently recurring problems.

The key idea is simple:

if a tool reduces cognitive load, removes duplication, and fits naturally into the codebase — it is worth adding.

Building Blocks

Each with a clearly defined responsibility within business operations

Commands

Exclusively for write operations: creating, updating, and deleting data. Each command represents a single atomic business operation like creating an order or confirming a payment. No data retrieval for presentation.

CreateOrderCommand ConfirmPaymentCommand

Queries

Exclusively for reading data with no side effects. Perform complex joins, eager loading, and data aggregation. Return data in the form required by the caller—models, collections, arrays, or DTOs. The read-side use-case layer.

GetOrderDetailsQuery ListProductsQuery

Actions

Encapsulate application logic that doesn't fit into commands or queries. Used for multi-step business scenarios requiring orchestration, conditions, validations, and branching logic. Always executed as a single complete operation.

PlaceOrderAction ProcessReturnAction

Value Objects

Transform primitive values into meaningful domain concepts with guaranteed invariants. Fail-fast validation at construction ensures data is either always valid or doesn't exist. No repeated validation needed throughout the system.

Email Money PostalCode

Query Builder Modifiers

Callable classes that accept and return a Laravel Query Builder. Encapsulate reusable query fragments like conditions, joins, and filters. Work at a lower abstraction level—conscious mixing that embraces the Query Builder as an effective tool.

WhereActiveModifier WithPaginationModifier

On the HTTP Layer

The HTTP layer handles requests and responses only. Core business logic never lives here.

Controllers are optional. Routes may directly delegate execution to application-level Actions, Commands, or Queries, either through controllers or minimal route closures used purely as entry points.

Controllers, when used, act as transport adapters for validation, authorization, middleware interaction, and response formatting. All business rules remain isolated in application-level objects, which may return data or, when appropriate, an HTTP response.

The system is designed around use cases, not controllers.

Ready to Explore?

Utilitarian Architecture is free and open source.