Skip to content
Mehedi Hasan Sagor

// blog

Laravel Production Checklist: Proven Best Practices to Keep Your App Fast, Secure, and Maintainable

Mehedi Hasan Sagor Oct 27, 2026 5 min read
Laravel Production Checklist: Proven Best Practices to Keep Your App Fast, Secure, and Maintainable

Running a Laravel app in production is more than just pushing code to a server. The decisions you make today affect scalability, security, and the cost of future changes. The following checklist is built on first‑principles and real‑world experience, so you can evaluate each item quickly and act on the ones that matter most for your team.

1. Code Quality and Architecture

  • Prefer Service‑Container Bindings Over Facades Facades are convenient but hide the underlying dependencies. Register concrete classes in AppServiceProvider and inject them via the constructor. This makes unit testing trivial.
// App\Providers\AppServiceProvider.php
public function register()
{
    $this->app->bind(
        App\Contracts\PaymentGateway::class,
        App\Services\StripeGateway::class
    );
}

// In a controller
use App\Contracts\PaymentGateway;

class OrderController extends Controller
{
    private $gateway;
    public function __construct(PaymentGateway $gateway)
    {
        $this->gateway = $gateway;
    }

    public function store(Request $request)
    {
        $this->gateway->charge($request->amount);
        // ...
    }
}
  • Domain‑Driven Folder Structure Keep the default app/Models, app/Http, etc., but add a app/Domain layer for business logic. Controllers become thin request‑handling shells, while services encapsulate use‑cases.

  • Avoid Fat Controllers If a controller method exceeds 30 lines, extract the logic into a service class or an Action (single‑purpose invokable class). This improves readability and testability.

  • Write Unit Tests First Aim for 70‑80 % coverage on core services. Use Laravel’s built‑in testing helpers; they spin up an in‑memory SQLite database, keeping the feedback loop fast.

2. Configuration and Environment Management

  • Never Store Secrets in .env on the Server Use your hosting platform’s secret manager (e.g., Laravel Vapor, AWS Parameter Store, or Docker secrets). In your code, reference config('services.stripe.key') rather than env('STRIPE_KEY') directly.

  • Cache Config and Routes Run php artisan config:cache and php artisan route:cache during deployment. This compiles the configuration files and route list into a single PHP file, reducing bootstrap time.

  • Separate Config for Each Environment Keep config/*.php environment‑agnostic and place environment‑specific values in the secret store. This prevents accidental leakage of dev settings into prod.

  • Version‑Control Only the Skeleton .env.example Include placeholders for every key your app needs, so new developers can spin up a local copy without guessing.

3. Performance Optimizations

  • Leverage Query Caching Frequently accessed read‑only data (e.g., product categories) should be cached. Laravel’s cache tags let you invalidate related keys in a single call.
$categories = Cache::tags(['catalog'])->remember('categories', now()->addHours(2), function () {
    return Category::all();
});
  • Use Eager Loading Wisely N+1 queries are a common source of latency. Use with() on relationships you know you’ll need, but avoid loading massive collections you never touch.

  • Queue Time‑Consuming Work Anything that can be deferred—emails, image processing, PDF generation—should be pushed to a queue. Laravel Horizon provides a clear dashboard for Redis‑backed queues.

  • Optimize Blade Rendering Turn on Blade component caching with Blade::componentCachePath() if you generate many dynamic components. Also, avoid heavy logic inside templates; move it to view composers or service classes.

  • Static Asset Pipeline Compile CSS/JS with Laravel Mix or Vite, enable versioning (mix.version()), and serve the compiled assets via a CDN. This reduces the time‑to‑first‑byte for end users.

4. Security Hardening

  • Enforce HTTPS Everywhere In AppServiceProvider::boot(), call URL::forceScheme('https'); for non‑local environments. Also enable HSTS headers via middleware.

  • Rate Limit Critical Endpoints Use Laravel’s built‑in ThrottleRequests middleware to protect login, password reset, and API token issuance routes.

Route::post('login', [AuthController::class, 'login'])
    ->middleware('throttle:5,1'); // 5 attempts per minute
  • Validate All Input Rigorously Never rely on client‑side validation alone. Use Form Request classes with explicit rules, and consider custom validators for business‑specific constraints.

  • Sanitize Output When rendering user‑generated HTML, use a library like HTMLPurifier to strip unsafe tags. Laravel’s e() helper escapes output by default, but for rich text you need an extra layer.

  • Keep Dependencies Updated Run composer outdated --direct weekly and apply security patches promptly. Automate this with Dependabot or Renovate to avoid manual drift.

5. Observability and Incident Response

  • Centralized Logging Ship logs to a log aggregation service (e.g., Papertrail, Loggly, or ELK). In config/logging.php, configure a daily channel for local fallback and a stack that includes the remote driver.

  • Health Checks Expose a /health endpoint that returns 200 OK only when the database, cache, and queue workers are responsive. Use Laravel’s Route::view with a simple closure that runs quick checks.

Route::get('health', function () {
    try {
        DB::connection()->getPdo();
        Cache::has('test');
        return response()->json(['status' => 'ok']);
    } catch (\Exception $e) {
        return response()->json(['status' => 'error'], 500);
    }
});
  • Metrics Collection Instrument key business events (order placed, user sign‑up) with Prometheus client libraries or Laravel’s built‑in Event::listen to push counters to a monitoring system.

  • Automated Deployments with Rollback Use a CI/CD pipeline that runs the full test suite, builds assets, and performs a zero‑downtime deployment (e.g., via Laravel Envoy or GitHub Actions with php artisan down/up). Keep the previous release artifact so you can rollback instantly if health checks fail.

  • Post‑mortem Process After any outage, document the timeline, root cause, and mitigation steps in a shared Confluence page. This habit turns incidents into learning opportunities and reduces future MTTR.


Quick Takeaways

  1. Inject, don’t Facade – improves testability.
  2. Cache config, routes, and query results – cuts boot time.
  3. Queue every non‑critical task – frees request threads.
  4. Rate‑limit and enforce HTTPS – basic but essential security.
  5. Add health checks and centralized logs – detect problems before users do.

Implementing even a subset of these practices will raise the reliability bar of your Laravel application and give your team confidence to ship faster.

  • Laravel
  • Best Practices
  • Php
  • Devops
  • Production