Scaling a Laravel Monolith Without Losing Your Mind
Modular boundaries, queue discipline and the database habits that let a monolith carry serious load for years.
A monolith is not a design failure. Most teams that rewrite into services do it because their monolith became disorganised, not because it became too big. Structure buys you years.
Draw module boundaries before you draw service boundaries
Group code by business capability — Billing, Catalogue, Identity — instead of by technical layer. Each module owns its models, its jobs and its public interface. Anything outside the module talks to it through that interface only.
What a module owns
- Its own Eloquent models and migrations
- Its jobs, events and listeners
- A thin public service class that other modules may call
Once boundaries are explicit, extracting a service later is a packaging exercise rather than an archaeology project.
Treat queues as a first-class part of the request
Anything that is not required to render the response belongs on a queue: emails, PDF generation, webhooks, search indexing, third-party sync. Give each workload its own queue and its own worker pool so a slow integration cannot starve transactional work.
A single default queue is the most common reason a healthy Laravel app feels slow under load.
Database habits that matter more than hardware
- 01Index for the queries you actually run, then verify with EXPLAIN.
- 02Kill N+1 queries at the source with eager loading and a query-count assertion in tests.
- 03Paginate everything, including internal admin screens.
- 04Move reporting reads to a replica so analytics never blocks checkout.
Cache with an eviction story
Caching without an invalidation plan is a bug with a delay. Prefer tagged caches keyed to the model that owns the data, and invalidate in the model's observer so no caller has to remember.
Measure before and after
Track p95 response time, queue wait time and slow-query count. When those three are visible on one dashboard, the decision about what to optimise next stops being an argument and starts being obvious.
Building something that has to scale?
I help teams design architecture, tighten performance and ship products that keep working as the business grows.