Every Laravel application handles a request through the same pipeline, whatever the app does. Knowing that pipeline makes debugging faster: when something is slow or wrong, you know which stage could be responsible. This is a general explanation of Laravel's request lifecycle (current versions, 11 and 12), with notes on where time is usually spent.

1. The entry point: public/index.php

The web server (nginx with PHP-FPM, Apache, or php artisan serve locally) sends every request that is not a static file to public/index.php. That file loads Composer's autoloader, boots the application from bootstrap/app.php, and hands the request to the HTTP kernel.

Where time goes: booting is cheap when caches are warm. In production, php artisan optimize caches configuration, routes, events and views so they are not rebuilt on every request, and OPcache keeps compiled PHP in memory. A missing cache shows up as every request being slower by a similar fixed amount.

2. Service providers

Before handling the request, Laravel registers and boots the application's service providers. Providers bind classes into the service container — the registry that later builds controllers and their dependencies — and run start-up code.

Where time goes: providers run on every request. A provider that makes a database query or an HTTP call in its boot() method taxes every single request, including ones that never use it. Deferred providers and lazy bindings avoid that.

3. Global middleware

The request then passes through global middleware — code that wraps every request: trimming strings, handling maintenance mode, trusted proxies, CORS. Middleware forms an onion: each layer can act before passing the request inward and again on the response on its way out.

4. Routing

The router matches the method and path to a route. Route model binding resolves parameters such as /posts/{post} into models (one query each), and the route's own middleware group runs — for the web group that means cookies, sessions and CSRF protection; for api, usually authentication and rate limiting.

Where time goes: session storage and authentication can each hit the database or cache. Route model binding adds a query per bound parameter — usually fine, occasionally a surprise when a route binds several models.

5. The controller

The container builds the controller, injecting its constructor and method dependencies, and calls the action. Form Requests validate input before the method body runs; a validation failure returns early with a 422 (or a redirect) without reaching your code.

This is where most application time is spent: business logic, Eloquent queries, calls to other services, dispatching jobs.

6. The database layer

Eloquent builds SQL and sends it through the database connection. Three patterns account for most database time in Laravel apps:

  • N+1 queries — a relation loaded inside a loop. Fix with eager loading (with()).
  • Loading more than needed — whole models where a select(), pluck() or count() would do.
  • Missing indexes — queries filtering or sorting on unindexed columns, which only hurt once the table grows.

7. The response

The controller returns a view, a JSON resource, a redirect or a plain value; Laravel converts it into a response. It travels back out through the middleware stack (which can add headers or cookies), is sent to the client, and only then do terminable middleware and afterResponse callbacks run.

Where time goes: rendering large Blade views or serialising big collections to JSON can cost more than the queries that loaded them.

Seeing the pipeline for a real request

The lifecycle above is the same for every request; what differs is how long each stage takes. A request trace makes that visible. Zerethon's Flow Laravel adapter records the request, the controller, each database query and any service or external call you wrap, so you can see which stage of this pipeline dominates a given endpoint. Start with finding the real bottleneck for how to read the result.

Quick checklist for a slow endpoint

  1. Is php artisan optimize run on deploy, and is OPcache enabled?
  2. Does any service provider do I/O in boot()?
  3. How many queries does the request run, and are any repeated?
  4. Is there an external HTTP call on the request path that could be cached or queued?
  5. Is response rendering or serialisation a significant share of the time?