1.8 seconds for one registration request. I put a timer around it on a project last month. 1.5 of those seconds was the welcome email going out over SMTP.
The user waits almost two seconds and looks at a spinner, for a handshake with a mail server he will never hear about.
Laravel 4.2 makes the fix one line:
Queue::push('SendWelcomeEmail', array('user_id' => $user->id));
The controller returns in 300 ms. A worker picks the job up and sends the email. php artisan queue:listen to start, beanstalkd or Redis behind it, the failed_jobs table for jobs that died.
Infrastructure fashion is not the point. The execution model of the application changes. Before: everything happens inside the request. After: the request only records an intent, and the slow work happens later.
“Later” has consequences, and I learned each one the hard way.
The HTTP response is gone when the job runs. You cannot show the user an error. The job handles its own failures: retries, logging, alerting.
The job can run twice. Worker dies after sending but before the ack, the queue redelivers. Every job must be safe to repeat. Check a flag before sending, or make the operation idempotent some other way. One user got the welcome email twice before I believed this.
Pass ids, not objects. The user row can change between push and execution. The job loads fresh data.
Queues are easy to add and hard to add correctly. Start with email: slow, non-critical, nobody dies if it arrives a minute late.