There's a gap between Laravel applications that work and Laravel applications that hold up in production under real traffic, real team development, and real maintenance cycles. After deploying 20+ Laravel apps to production β€” from small client portals to multi-tenant SaaS platforms β€” these are the practices I consider non-negotiable.

1. Service Layer Architecture (Not Fat Controllers)

The most common Laravel anti-pattern I see is business logic in controllers. Controllers should do one thing: translate HTTP requests into application actions and return responses. Business logic belongs in service classes.

The pattern I use: every significant business operation gets a dedicated service class in app/Services/. The controller instantiates the service (or uses dependency injection) and calls a single method. The service handles the business logic, orchestrates model interactions, and dispatches events or jobs as needed.

This makes testing trivial β€” you can test the service class directly without going through HTTP β€” and keeps controllers readable and consistent across the application.

2. Form Request Validation β€” Always

Validation logic in controllers is a maintenance problem. Every endpoint that accepts input should have a dedicated FormRequest class. This keeps validation logic out of controllers, provides a clean place to add authorization logic, and makes your validation rules self-documenting.

The additional benefit: custom failedValidation() methods in FormRequest classes give you centralized control over how validation errors are returned β€” critical for API endpoints that need consistent error response formats.

3. Repository Pattern for Complex Queries

For applications with complex reporting, multi-table queries, or queries that appear in multiple places, a Repository pattern prevents duplication and provides a clean abstraction over Eloquent. Interfaces define the contract; Eloquent implementations fulfill it.

I don't use this everywhere β€” simple CRUD operations don't need the overhead. But for any query that appears more than twice in the codebase, a repository method pays for itself immediately.

4. Queue Everything Slow

Any operation that takes more than ~200ms should not block the HTTP response: email sending, PDF generation, image processing, external API calls, webhook delivery. Push these to Laravel queues with Redis as the driver.

The operational pattern: use Laravel Horizon for queue monitoring in production. Set up separate queue workers for different priority levels β€” a critical queue for time-sensitive operations (password reset emails, payment confirmations) and a default queue for everything else.

Failed jobs are inevitable. Configure failed_jobs table and set up monitoring alerts β€” I use Laravel Telescope in staging and a custom Slack notification for failed jobs in production.

5. Caching Strategy: Be Deliberate

Laravel's cache system is powerful but easy to misuse. The pattern I follow: cache data that is expensive to compute, changes infrequently, and is safe to serve stale for a defined period.

Site settings, navigation menus, and configuration data that gets read on every request β€” cache indefinitely and bust on update with tagged cache groups. Heavy report queries β€” cache for 5-15 minutes with a scheduled job to warm the cache before expiry. User-specific data β€” cache by user ID with a short TTL or don't cache at all.

The mistake I see most often: developers cache things and then forget to bust the cache on updates. Use Laravel's Cache tags and always write the cache invalidation logic at the same time as the cache-setting logic.

Laravel production architecture diagram β€” service layer, queues, caching, and deployment pipeline
Clean architecture in Laravel: controllers stay thin, business logic lives in service classes, and slow operations go to queues.

6. Zero-Downtime Deployment with Laravel Envoy or Deployer

Deploying Laravel with git pull on the server is asking for downtime. The correct approach: atomic deployments where the new release is prepared completely before traffic is switched to it.

My deployment flow with Deployer: pull the release to a new timestamped directory, run composer install --no-dev, run migrations, warm config and route caches, then atomically symlink current to the new release. The old release stays in place for instant rollback. The entire switchover is a symlink update β€” effectively zero-downtime.

Always run migrations with php artisan migrate --force as part of deployment. Write backward-compatible migrations β€” new nullable columns before removing old ones, so a rollback doesn't break the previous release.

7. Horizon, Telescope, and Pulse in Production

Running Laravel in production without observability is flying blind. My standard setup: Laravel Telescope in staging only (too expensive for high-traffic production), Laravel Horizon for queue monitoring in all environments, and Laravel Pulse for real-time performance metrics in production.

Pulse (introduced in Laravel 10) gives you request throughput, slow queries, failed jobs, and cache hit rates in a single dashboard. It's lightweight enough for production and has caught several performance regressions before clients noticed them.

8. API Authentication: Sanctum for SPAs, Passport Only If You Need OAuth2

I've seen developers reach for Passport when they don't need it. Unless you're building an OAuth2 server that issues tokens to third-party clients, Sanctum handles every API auth use case β€” SPA cookie authentication, mobile app token auth, and simple API key authentication. It's simpler to configure, simpler to debug, and has fewer moving parts in production.

The Underlying Principle

Every practice here serves the same goal: make the application easier to understand, change, and operate six months from now when the project is under maintenance by someone who didn't write it β€” or by you, when you've forgotten the original context.

Building with Laravel? Check out my Laravel projects or get in touch to discuss your application requirements.

Related Service

πŸ’» Web Development

Custom websites and web applications built with PHP, Laravel, WordPress, and React β€” fast, secure, scalable, and tailored to your business goals.

Explore Web Development →