Deferred providers — loading only when needed
Concept
Deferred service providers load their bindings only when a bound class is actually needed, rather than on every request. This reduces bootstrap time for applications with many providers where only a subset of services are used per request.
How deferral works: A deferred provider implements the $defer property (Laravel ≤ 9) or the DeferrableProvider interface (Laravel 10+). It also declares provides(): array — the list of class names it registers. Laravel skips the provider's register() during bootstrap. Only when code calls app()->make(SomeClass::class) for one of the declared classes does Laravel load and register that provider.
DeferrableProvider interface: In Laravel 10+, implement Illuminate\Contracts\Support\DeferrableProvider. No $defer = true property needed. The interface signals deferral.
When to use deferred providers:
- Services that are NOT used on most requests (background processing services, CLI-only services, rarely-used third-party integrations).
- Heavy providers that perform significant work during
register().
When NOT to use:
- Services used on every request (auth, session, database, cache) — the check overhead doesn't pay off.
- Services that need to run boot logic (event listeners, routes) on every request.
Important: Deferred providers only defer register(). boot() still runs on every request because boot-time actions (event listeners, routes) are needed globally.
Code Example
<?php
namespace App\Providers;
use Illuminate\Contracts\Support\DeferrableProvider;
use Illuminate\Support\ServiceProvider;
// Laravel 10+ — implement DeferrableProvider interface
class PdfServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
// This register() runs ONLY when PdfGenerator is actually needed
$this->app->singleton(\App\Services\PdfGenerator::class, function($app) {
// Expensive: loads large library, connects to external PDF service
return new \App\Services\PdfGenerator(
config('services.pdf.api_key'),
config('services.pdf.endpoint'),
);
});
$this->app->alias(\App\Services\PdfGenerator::class, 'pdf');
}
/**
* Declare what this provider registers.
* Laravel uses this to know when to load the provider.
*/
public function provides(): array
{
return [
\App\Services\PdfGenerator::class,
'pdf',
];
}
}// config/app.php — register like any other provider
'providers' => [
// ...
App\Providers\PdfServiceProvider::class, // deferred — loaded only when PdfGenerator is needed
],// Usage — PdfServiceProvider registers only when this line is hit
$pdf = app(\App\Services\PdfGenerator::class);
// or: app('pdf')
// or via injection: __construct(private readonly PdfGenerator $pdf) {}
// In most API responses where PDF is not needed — zero overhead from this provider