Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Iron Queue Laravel Package

laravelcollective/iron-queue

IronQueue is a Laravel queue driver for IronMQ (Iron.io). It lets Laravel applications push, receive, and process queued jobs through IronMQ using the familiar Laravel queue API, making it useful for cloud-hosted background job processing.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install the connector (Laravel 5.x / Lumen only).

composer require laravelcollective/iron-queue

The package pulls in the iron-io/iron_mq client and restores the iron queue driver that Laravel removed after 5.x. If Composer resolves to a Laravel 6+ app, stop here — the package was last released in 2018 and targets the 5.x Illuminate\Queue contracts.

2. Register the service provider. Laravel (config/app.php):

'providers' => [
    // ...
    LaravelCollective\IronQueue\IronQueueServiceProvider::class,
],

Lumen (bootstrap/app.php):

$app->configure('queue');
$app->register(LaravelCollective\IronQueue\IronQueueServiceProvider::class);

Lumen has no config/queue.php by default — create one; the driver is resolved from it.

3. Add the connection to config/queue.php.

'connections' => [
    'iron' => [
        'driver'  => 'iron',
        'host'    => env('IRON_MQ_HOST', 'mq-aws-us-east-1.iron.io'),
        'project' => env('IRON_PROJECT_ID'),
        'token'   => env('IRON_TOKEN'),
        'queue'   => env('IRON_QUEUE', 'default'),
        'encrypt' => false,
    ],
],

Set QUEUE_CONNECTION=iron (or QUEUE_DRIVER on older 5.x point releases) and put the three IRON_* values in .env.

4. Look first at: the package's src/ for the exact provider/connector class names (they track the old framework IronConnector / IronQueue classes), then your Iron.io dashboard — confirm the project ID, token, and the host region of the queue cluster. A token is region-scoped; a wrong host returns auth failures that look like bad credentials.

5. First use case — a queued job round-trip.

php artisan make:job SendWelcomeEmail
class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public int $userId) {}

    public function handle()
    {
        User::find($this->userId)->sendWelcomeMail();
    }
}
SendWelcomeEmail::dispatch($user->id);
php artisan queue:work iron --tries=3 -v

If the worker picks the job up and the IronMQ dashboard shows the message draining, you're wired correctly.

Implementation Patterns

Named queues for workload isolation. IronMQ supports multiple queues per project; mirror them in Laravel:

ProcessPodcast::dispatch($podcast)->onQueue('media');
SendInvoice::dispatch($order)->onQueue('billing');

Run workers per tier so a slow media backlog can't starve billing:

php artisan queue:work iron --queue=billing --tries=5
php artisan queue:work iron --queue=media,default --tries=1

Delays for scheduled-ish work. IronMQ holds the message server-side until the delay elapses, so you don't need a scheduler for short offsets:

SendTrialReminder::dispatch($user)->delay(now()->addHours(48));

This is the cheapest pattern for "do X in N minutes" when a cron would be overkill — but see the delay ceiling in Gotchas.

Retries and backoff. Let the worker own the retry policy rather than relying on IronMQ reservation counts:

php artisan queue:work iron --tries=5 --backoff=30 --sleep=3

--backoff gives you escalating redelivery without touching the IronMQ config. Keep tries in the job (public $tries = 3;) when the semantics belong to the job rather than the deployment.

Explicit connection switching. When part of the app stays on Redis locally and IronMQ in production:

SendInvoice::dispatch($order)->onConnection('iron');

or set $connection = 'iron'; on the job class. This is how you keep php artisan test fast while production traffic goes to Iron.

Connection health as a first-class concern. Because IronMQ is a hosted dependency, wrap the enqueue path so failures surface as your own exception, not a raw IronMQ_Exception:

try {
    SendInvoice::dispatch($order);
} catch (\Throwable $e) {
    Log::error('iron dispatch failed', ['order' => $order->id, 'e' => $e->getMessage()]);
    SendInvoice::dispatch($order)->onConnection('database'); // fallback spool
}

A database or redis fallback connection is the standard way to survive an Iron.io outage without losing jobs — dispatch to the fallback, and a periodic sweeper re-dispatches to iron.

Testing stays driver-agnostic. Queue::fake() intercepts at the facade, so it works unchanged:

Queue::fake();
SendInvoice::dispatch($order);
Queue::assertPushedOn('billing', SendInvoice::class);
Queue::assertPushed(SendInvoice::class, fn ($job) => $job->orderId === $order->id);

You only need a live IronMQ project for integration tests against queue:work.

Deployment shape. Run workers under Supervisor (or your platform's process manager) with queue:work, not queue:listen, for the usual reason — work boots the app once per long-running loop; use listen only while developing. Restart workers on deploy via php artisan queue:restart.

Gotchas and Tips

The package is archived — treat it as frozen, not maintained. There will be no fix for a PHP 8.1 deprecation, a Illuminate\Queue contract change, or an iron-io/iron_mq CVE. Pin composer.json tightly and plan a migration path (SQS and Redis are first-class drivers in modern Laravel and need no connector).

Verify Iron.io itself is still a viable target before you invest. Iron.io's hosted IronMQ has had a turbulent history since acquisition; confirm your account, project, and endpoint are alive and that your plan's limits match your volume. If you're building something new, choose a driver the current framework supports — this connector's value is almost entirely for legacy 5.x apps that can't move.

Wrong host looks exactly like bad credentials. Tokens are cluster-scoped. Use the host shown in your Iron.io project settings (e.g. mq-aws-us-east-1.iron.io), and double-check it when copying .env between environments.

Message size is a hard IronMQ limit (64 KB). Serialized Eloquent models with eager-loaded relations blow past this without warning. Pass IDs and re-query in handle(), and keep SerializesModels in use so you don't smear state across deployments.

encrypt => true changes the wire format. If you flip it, every producer and consumer must agree — mixing encrypted and plain payloads across two deploys produces garbage jobs that fail deserialization. Roll it out with a drain, or leave it off and rely on transport security.

retry_after doesn't mean what it does on Redis/database. IronMQ owns reservation and visibility timeouts server-side. If you see jobs reappearing mid-processing, the fix is usually the IronMQ reservation timeout (or a worker that's slower than it) — not config/queue.php. Keep queue:work --timeout comfortably below the reservation window.

Delay has a server-side ceiling. IronMQ caps delay (commonly quoted at 7 days). ->delay() beyond the cap fails at push time, not at dispatch time, so a try/catch around the dispatch is the only place you'll see it. For longer horizons, use the scheduler and a zero-delay dispatch.

Failed jobs live in failed_jobs, not IronMQ. Standard commands work — php artisan queue:failed, queue:retry all, queue:forget {id} — but IronMQ's own dashboard won't show them. Check both places when triaging.

Newer queue features are absent. No job batching, no RateLimited middleware semantics, no Horizon, no queue:clear-style driver introspection, no Queue::size() you can trust. If your design depends on those, this driver is the wrong layer.

Debugging order that actually converges: (1) php artisan queue:work iron -v in the foreground; (2) IronMQ dashboard to confirm the message was pushed and reserved; (3) failed_jobs table + storage/logs/laravel.log; (4) verify the iron-io/iron_mq HTTP calls with a tiny standalone script using the same token/host/project. Ninety percent of "it's not working" is a credential/region mismatch caught at step 4.

Extension point if you must patch. Register your own driver with Queue::extend('iron', fn () => new MyIronConnector(...)) in a boot() method that runs after the package provider, so you can decorate push/pop for logging or payload rewriting without forking. Forking is the other option — but on an archived package, a thin local override is the only version you'll be able to maintain.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console