Laravel’s singleton() reuses a resolved service for the lifetime of the container. scoped() reuses it only for one request or job lifecycle, then Laravel flushes that scoped instance when the next lifecycle begins. Choose scoped() for state that should be shared within a unit of work but not carried into the next one.
How scoped() and singleton() differ
| Binding | Reuse boundary | What happens in a later request or job |
|---|---|---|
singleton() |
The same resolved instance is returned on subsequent container resolutions. | The instance remains shared for the container’s lifetime; it is not automatically reset at each request or job boundary. |
scoped() |
The same resolved instance is returned within one Laravel request or job lifecycle. | Laravel flushes scoped instances when a new lifecycle starts, so a later request or job can resolve a fresh instance. |
Laravel’s Laravel 13 service-container documentation describes scoped() as binding a class or interface for one resolution within a request or job lifecycle. Laravel 10’s service-container documentation describes the same boundary.
As an Amazon Associate I earn from qualifying purchases.
Why the lifecycle boundary matters
In a traditional request-per-process setup, application state often disappears when the request finishes. Long-lived workers change that assumption. Laravel’s Octane documentation explains that the application remains in memory across requests. A singleton that captures a request or other request-specific state can therefore retain old data and expose it while handling a later request.
A scoped binding is useful when multiple consumers should share one object during the current request or job, but that object’s state should not be reused by the next unit of work. This is a lifetime and state-isolation choice, not a general performance optimization; the documentation cited here makes no performance claim for scoped bindings.
#1 Best Overall
Choose a binding based on the state it holds
Use singleton() for container-wide shared instances
Register a service as a singleton when the same resolved instance is intended to remain shared for the container’s lifetime. Avoid storing request- or job-specific state in that instance if the application runs in a long-lived worker.
Use scoped() for request- or job-specific context
For example, a CurrentTenant context object might hold the tenant selected for the current request. With a scoped binding, consumers resolving it during that request share the same object; when a new request or job lifecycle begins, Laravel flushes the scoped instance so the next resolution can provide a fresh context. This is an illustrative use, not a requirement that every tenant service be scoped.
Laravel’s Octane guidance also recommends passing a service only the request data it needs at runtime rather than retaining a request or container instance in a long-lived singleton’s constructor. scoped() addresses the lifetime of its container binding; it does not automatically clear arbitrary static properties or application globals.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsRegistering a scoped binding
Register scoped services through the application container, commonly in a service provider. The container API documents both scoped() and scopedIf(); use the conditional form when the binding should be registered only if it is not already present.
Rank #3
$this->app->scoped(CurrentTenant::class, function ($app) {
return new CurrentTenant();
});
The container API also lists forgetScopedInstances() for clearing scoped instances. For normal request and job boundaries, use Laravel’s documented scoped lifecycle rather than relying on a manual clear as a substitute for choosing the right binding.
See the Laravel 13 container API reference for the registration and clearing methods.
Rank #4
What “knows when to die” means—and does not mean
The phrase is shorthand for a container lifetime boundary: Laravel flushes scoped instances when a new request or job lifecycle begins. It does not promise when PHP will release every object reference or run garbage collection. Code holding a separate reference can keep an object alive, and the scoped binding does not reset state stored elsewhere.
Recommended Free Tools
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




