Architecture
Recognising the pattern you already live inside, and pricing the exit.
43 articles · 418 minutes of reading
Every legacy system was somebody's clean architecture once. The patterns were right when they went in. What changed is the second use case, the one that turned up eighteen months later and did not fit the shape the first one had already carved.
So architecture work is mostly recognition. Which pattern are you already inside, and what does it cost to leave? A model nobody wants to touch is an architecture report. So is a test suite that needs six mocks to assert one thing. Both are telling you where the seams went wrong, for free, before anyone writes a proposal.
The position I keep returning to is that the rewrite is almost never the answer, and the team proposing it usually knows. Strangle it instead. Take one seam at a time, keep shipping while you do, and accept that the result will look less tidy than the diagram you wanted.
Start here
The Rewrite You Should Not Do
You have run the diagnostics and you have a list. Now price the three options honestly, including the one where you do nothing, which is right more often than the other two put together.
Aug 2026 · 8 min read
The Second Pattern: Bulkhead
Carrier B did not go down, it got slow, and every worker sat inside an eleven second call that returned a valid 200. Circuit breakers ask the wrong question about that.
Sept 2026 · 13 min read
Your Test Suite Is an Architecture Report
A slow Laravel test suite gets treated as a tooling problem. It is usually a coupling measurement, and the number worth watching is not how long the suite takes.
Aug 2026 · 8 min read
Nobody Wants To Touch That Model
Every Laravel codebase has a model people route around. Counting its lines is the least useful thing you can do to it, and extracting traits is how the count gets hidden rather than fixed.
Aug 2026 · 8 min read
Everything in Architecture
The Second Pattern: The Ones I Left Out
Five patterns I know well, that come up constantly, and would not reach for in PHP. Not because they are bad ideas, but because of what the runtime does and does not give you.
The Second Pattern: Blackboard
A pipeline works until one step both needs and improves the same piece of information. That is a cycle, and a topological sort has exactly one contract: there are no cycles.
The Second Pattern: Event-Carried State Transfer
A consumer that receives an ID and immediately asks you for the record has not been decoupled from you. It has been given a slightly slower way to call your API.
The Second Pattern: Process Manager
Everyone calls it a Saga. Most of the time it is a Process Manager, and the muddle is why teams adopt the word and then never write the compensations it never promised them.
The Second Pattern: Bulkhead
Carrier B did not go down, it got slow, and every worker sat inside an eleven second call that returned a valid 200. Circuit breakers ask the wrong question about that.
The Second Pattern: Claim Check
A payload that is 40KB almost always and 12MB occasionally cannot be sized for. Making it smaller is not the fix, because the problem is the channel it is moving through.
The Second Pattern: Idempotent Receiver
Select then insert handles the easy half of duplicate delivery and misses the concurrent case, which is the half that actually fires. This time the framework has already done it properly.
The Second Pattern: Transactional Outbox
Commit then notify loses messages. Notify then commit sends lies. The dual write problem has no clever solution, and Tempest ships more of the machinery than it advertises.
The Second Pattern: Anti-Corruption Layer
Carrier B speaks GraphQL, so the response arrives shaped like your query and feels like it belongs to you. It does not, and their vocabulary is now load-bearing in your domain.
The Second Pattern: Specification
Nine optional parameters is the symptom. The problem is a business rule that has to run in SQL and in memory, written twice and quietly drifting apart.
Every Feature Touches Ten Files
Ten files open for a one line change is either layering working correctly or one idea smeared across a codebase. The count does not tell you which, and git history does.
It Was Fine Until We Added A Second One
Every trigger in this series has been a second something. That is not a coincidence, and it is the only signal in here reliable enough to act on.