What you'll learn
Use Laravel's queues, events, notifications, scheduler, cache, and locks to make slow workflows responsive and resilient. Keep domain facts distinct from asynchronous delivery mechanics.
By the end of this lesson, you'll be able to:
- Dispatch and operate queued jobs
- Separate events from listeners and notifications
- Coordinate cache locks and scheduled tasks
Core mental model
Professional PHP is less about memorizing APIs and more about choosing a clear boundary for each responsibility. Use this table as a decision guide while reading the examples.
| Concept | What it protects | Decision rule |
|---|---|---|
| Job | Retryable background command | Queue slow or failure-prone work outside the response. |
| Event | Fact already occurred | Publish to decouple optional reactions from the transaction. |
| Cache lock | Cross-process exclusion | Guard short work that must have one active owner. |
Professional workflow
Build the feature in small, verifiable steps. Each step leaves the system in a state you can test.
- Describe the Laravel asynchronous workflow boundary: its inputs, outputs, invariants, and expected failures.
- Implement the smallest happy path behind an explicit contract.
- Add validation and translate low-level failures into language the caller understands.
- Exercise the boundary with realistic data, then inspect output, logs, and resource cleanup.
- Refactor only after behavior is protected by a repeatable check.
Make the boundary visible
Guided code lab
Design a retryable job
The job stores an identifier, defines bounded retry timing, and can be unique while pending.
<?php
final class GenerateCourseReport implements ShouldQueue, ShouldBeUnique
{
use Queueable;
public int $tries = 4;
public function __construct(public readonly int $courseId) {}
public function uniqueId(): string { return (string) $this->courseId; }
public function backoff(): array { return [10, 60, 300]; }
public function handle(ReportGenerator $reports): void
{
$reports->generate($this->courseId);
}
}Schedule one cluster-wide run
The scheduler avoids overlap, and onOneServer prevents every application instance from dispatching the same work.
<?php
use Illuminate\Support\Facades\Schedule;
Schedule::job(new RebuildCourseMetrics)
->hourly()
->withoutOverlapping(minutes: 55)
->onOneServer()
->name('course-metrics');Production practice
Contract
Dispatch durable work after the database commit and make handlers safe when records change or disappear.
Verification
Use Queue, Event, Notification, and Mail fakes for dispatch behavior; separately test real handlers and failure hooks.
Operations
Supervise workers, restart them on release, monitor failed jobs and age, and keep scheduler execution observable.
Common failure mode
Independent workshop
Add a publish workflow that emits an event, updates cached pages, notifies followers, and queues a unique analytics job.
Your finished workshop must include:
- After-commit event flow
- Retry/uniqueness/failure policy
- Scheduler and worker operations checklist
Definition of done
Recap & quick check
Key takeaways
- Jobs express background commands.
- Events describe completed facts.
- Queued handlers must tolerate retries and stale state.
- Workers and schedules are production processes.
Quick check
1. When should a job that needs new rows dispatch?
2. What prevents concurrent copies of scheduled work?
3. What should a domain event be named as?
Keep the workshop: later phases deliberately build on these boundaries, so today's small example can become part of your portfolio architecture.