Skip to main content
The PHP SDK ships a Laravel queue driver so php artisan queue:work just works. dispatch() pushes to AsyncBase; a worker pulls, runs your handle(), and acks on success / nacks on throw.
composer require asyncbase/asyncbase
The service provider is auto-discovered via composer’s extra.laravel.providers. No manual registration needed.

Configure

.env

QUEUE_CONNECTION=asyncbase
ASYNCBASE_KEY=sk_live_...
ASYNCBASE_BASE_URL=https://api.asyncbase.dev

config/queue.php

Add an asyncbase connection:
'connections' => [
    // ... existing connections

    'asyncbase' => [
        'driver'             => 'asyncbase',
        'key'                => env('ASYNCBASE_KEY'),
        'base_url'           => env('ASYNCBASE_BASE_URL'),
        'queue'              => env('ASYNCBASE_QUEUE', 'default'),
        'group'              => env('ASYNCBASE_GROUP', 'laravel-workers'),
        'visibility_seconds' => 60,
    ],
],
That’s it. Laravel now treats AsyncBase like any other queue driver (redis, sqs, database).

Dispatch + work

// app/Jobs/SendWelcomeEmail.php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public readonly string $to) {}

    public function handle(): void
    {
        // your work here
    }
}
Dispatch from anywhere in your app:
SendWelcomeEmail::dispatch('jane@example.com');
// Or with a delay:
SendWelcomeEmail::dispatch('jane@example.com')->delay(now()->addSeconds(30));
// Or target a specific queue name:
SendWelcomeEmail::dispatch('jane@example.com')->onQueue('emails');
Run the worker:
php artisan queue:work
# or target this connection explicitly:
php artisan queue:work asyncbase --queue=default --tries=3
Under supervisor / systemd:
[program:asyncbase-worker]
command=php /var/www/html/artisan queue:work --queue=default --tries=3
autostart=true
autorestart=true
user=www-data
stdout_logfile=/var/log/asyncbase-worker.log

Mapping — Laravel ↔ AsyncBase

Laravel conceptAsyncBase
Queue::push / dispatchPOST /v1/queues/{name}/messages
$job->delete() (on success)POST .../ack
$job->release() (on throw)POST .../nack — server applies exp-backoff
$job->fail() (max tries)final nack → server moves to DLQ
Laravel $triesAsyncBase retries (default 3)
Laravel retry_afterAsyncBase visibility_seconds
Laravel’s release($delay) passes a client-chosen delay. AsyncBase ignores it — the server decides backoff based on the attempt number (2^attempt × 1000 ms). To customize, set retries per-send via the raw SDK instead of dispatch.

Raw SDK access

Need fine-grained control (custom delay, FIFO groups, dedup)? Inject the raw Queue client:
// AppServiceProvider::register()
$this->app->singleton(AsyncBase\Queue::class, fn () =>
    new AsyncBase\Queue(env('ASYNCBASE_KEY'))
);
Then:
use AsyncBase\Queue;

public function send(Request $req, Queue $q)
{
    $r = $q->send('emails', [...], delay: '30s', fifoGroup: 'user-' . $req->user()->id);
    return response()->json(['id' => $r->id]);
}
Mix and match — dispatch() for regular jobs, raw $q->send() for advanced features.

Testing

Use Laravel’s fake queue:
Queue::fake();
SendWelcomeEmail::dispatch('jane@example.com');
Queue::assertPushed(SendWelcomeEmail::class);
The real driver is bypassed — no AsyncBase API calls in tests.

Horizon + stats

Horizon + queue:monitor rely on queue-size probes that AsyncBase doesn’t expose yet (pendingSize, delayedSize, reservedSize). The driver returns 0 for all, so Horizon won’t crash but also won’t show live sizes. Dashboard at app.asyncbase.dev is the source of truth for live queue depth.