A job is a class that knows how to run a unit of work later.
php artisan make:job SendWelcomeEmail
class SendWelcomeEmail implements ShouldQueue
{
use Queueable;
public function __construct(public User $user) {}
public function handle(): void
{
Mail::to($this->user)->send(new WelcomeMail($this->user));
}
}
Dispatch from anywhere:
SendWelcomeEmail::dispatch($user);
SendWelcomeEmail::dispatch($user)->onQueue('emails');
SendWelcomeEmail::dispatch($user)->delay(now()->addMinutes(5));
The ShouldQueue interface is the magic switch — Laravel serializes the job, drops it on the configured queue driver (database, redis, sqs, etc.), and the worker picks it up:
php artisan queue:work
Idempotency
A worker can crash mid-job. Design handle() so re-running is safe (use firstOrCreate, idempotent API calls, etc.). Set public int $tries = 3; for automatic retries with backoff.