Async work with Messenger
Don't make users wait while you send emails or process uploads. With Messenger, you describe the work as a message: a tiny immutable class.
A handler does the actual work. Dispatching from your controller is one line: $bus->dispatch(new SendWelcomeEmail($user->getEmail())). The controller returns instantly; the message goes to a queue (Doctrine, Redis, RabbitMQ, SQS...).
A worker process consumes the queue. Retries with exponential backoff, failure storage, rate limiting and parallel workers are all built in and ready to configure.
<?phpnamespace App\Message;class SendWelcomeEmail{ public function __construct( public readonly string $userEmail, ) { }}<?phpnamespace App\MessageHandler;use App\Message\SendWelcomeEmail;use Symfony\Component\Mailer\MailerInterface;use Symfony\Component\Messenger\Attribute\AsMessageHandler;use Symfony\Component\Mime\Email;#[AsMessageHandler]class SendWelcomeEmailHandler{ public function __construct( private MailerInterface $mailer, ) { } public function __invoke(SendWelcomeEmail $message): void { $email = (new Email()) ->to($message->userEmail) ->subject('Welcome aboard!') ->text('Thanks for signing up.'); $this->mailer->send($email); }}$ php bin/console messenger:consume async