Laravel Deadlocks: Queue Jobs That Already Ran End Up in failed_jobs Laravel queue workers on MySQL versions below 8.0.1 — or on servers where Laravel misreads the database version — reserve jobs using a plain FOR UPDATE lock and can deadlock on the DELETE, leaving jobs that already ran in the failed_jobs table. A single tinker line reveals which locking mechanism a given installation uses. The finding matters for developers running Laravel queues on older MySQL, who can check their lock type before deadlocks cause duplicate job failures. Below MySQL 8.0.1, or on a server Laravel misreads, workers reserve jobs with a plain FOR UPDATE and can deadlock on the DELETE. One tinker line shows which lock yours use. Get my monthly newsletter with what I learn from running Spatie, building Oh Dear, and maintaining 300+ open source packages. Practical takes on Laravel, PHP, and AI that you can actually use. No spam. Unsubscribe anytime. You can also follow me on X. "As a Laravel developer, this is the one newsletter I most look forward to. Freek has a talent for distilling packages or techniques down to something immediately useful - one tip can save you hours and even weeks. It's concise and practical and highly relevant."