When I tell other developers that the backend of Rozuro is written in plain PHP 8.2, with no framework underneath it, the reaction is roughly evenly split. Half think it is a refreshing choice and ask follow-up questions. The other half assume I must be doing something wrong and tactfully change the subject. Both reactions are fine. The choice is unusual enough that it deserves a real explanation.
I have shipped production code on Laravel, Symfony, Slim, CodeIgniter, and a handful of in-house frameworks at various agencies. I am not a framework-hater. They are useful tools for the projects they fit. For Rozuro, the math came out differently.
The first thing that pushed me away from a framework was the size of the runtime. Modern PHP frameworks ship with a lot of plumbing. Service containers, event dispatchers, middleware pipelines, ORMs, queue abstractions, plus the documentation that explains how all of that fits together. For a billing system, ninety percent of that plumbing is not what I need. What I need is a request, a router, a database connection, and predictable validation. The remaining ten percent of what a framework offers is the part I would replace within a year because it does not fit my domain anyway. The cost of a framework I am going to fight on the parts that matter to me is higher than the cost of writing those parts myself.
The second reason is upgrade churn. I have watched too many projects spend a quarter migrating from one major framework version to the next, not because the migration delivered any product value, but because the framework moved on and the security patches stopped. With plain PHP I am upgrading my own code only when I want to, and PHP itself is one of the few language runtimes that takes backwards compatibility seriously. The same code I wrote in 8.0 still runs on 8.4 with about three deprecation warnings, all of which are improvements.
The third reason is that a billing system has unusually strict requirements around determinism and audit. I want to know exactly what happens between a POST request landing on my server and a row being committed to the ledger. With a framework that path is long and goes through a lot of magic. With plain PHP it is a function that takes a request, validates it, opens a transaction, writes the ledger lines, and commits. I can read it top to bottom in fifteen minutes. When something goes wrong in production, that fifteen minutes is exactly the thing I want to be able to do.
The honest counter-arguments. I am writing my own validation layer instead of using the framework’s, which means I have to think about edge cases somebody else has already thought about. Authentication and session handling I built from scratch on top of PHP’s session library, which is fine, but means I do not get the framework’s hardening for free. Migrations are a hand-rolled SQL script with idempotent CREATE statements rather than a framework migration tool. Each of those is more work than reaching for the framework version.
The trade I made is more work upfront for less work later. So far that trade has paid off. The codebase is small enough that any new developer can read it in a week. The tests are mostly integration tests against a real database, because that is what I trust. The architecture is the boring three layers you would draw on a napkin: HTTP handlers, domain services, repositories. The most clever thing in the code is the invoice numbering logic, and it is clever because invoice numbering needs to be.
I do not recommend this approach for everyone. If you are building a CRUD app for an existing business with thirty developers, you are absolutely better off on Laravel or Symfony. The framework’s defaults are good and the cost of skipping them is high. If you are building a small, sharp tool with a complex domain core and you intend to be running it for ten years, plain PHP is a real option. People underrate it because it does not fit the resume conversation. The codebase rewards you regardless.
If you have war stories from going framework-less or going back to a framework, I would like to hear them — contact us.
Love, Marten.