timofrenzel/laravel-async-bus

Buffered and external async processing layer for Laravel with hash deduplication, TTL, distributed overflow spooling, protected API endpoints, Redis Streams/SQS/Beanstalk external jobs, optional dashboard and observability endpoints.

Maintainers

Package info

github.com/TimoFrenzel/laravel-async-bus

pkg:composer/timofrenzel/laravel-async-bus

Transparency log

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0-rc2 2026-08-09 19:22 UTC

This package is auto-updated.

Last update: 2026-08-12 05:06:36 UTC


README

Version: 1.0.0-rc2 Public API: DTO-only

Laravel Async Bus is a Laravel package for high-frequency asynchronous processing where ordinary one-job-per-event queues are not enough. It provides:

  • BufferedQueue for deduplicated, delayed and batched state updates.
  • ExternalQueue for JSON job envelopes on Redis Streams, SQS or Beanstalk.
  • Projection Framework for rebuildable read models, search indexes and materialized views.
  • Overflow spool for Redis pressure handling.
  • Failed-item handling, worker/cluster visibility, metrics, dashboard and protected OpenAPI documentation.

It is not a drop-in replacement for Laravel Queue. Use Laravel Queue for ordinary background jobs. Use Async Bus when you need dedupe, batching, projection rebuilds, external workers, queue-driver abstraction or operational visibility.

Documentation

Start with:

German introduction: README.de.md.
English introduction: README.en.md.

Choosing the right processing model

Need Use
Ordinary one-off PHP background job Laravel Queue
Concrete JSON job that must run once ExternalQueue
Many changes for the same business key should collapse BufferedQueue
Rebuildable derived state/read model/search index Projection Framework

Short rule: ExternalQueue transports jobs. BufferedQueue collapses state changes. Projections define rebuildable derived state.

Installation

composer require timofrenzel/laravel-async-bus
php artisan vendor:publish --tag=async-bus-config

Start from the example environment:

env/async-bus.example.env

Then verify:

php artisan async-bus:config:verify
php artisan async-bus:config:audit
php artisan async-bus:docs:verify
php artisan async-bus:openapi:verify

Minimal .env

ASYNC_BUS_ENABLED=true
ASYNC_BUS_REDIS_CONNECTION=default
ASYNC_BUS_PREFIX=async_bus:

ASYNC_BUS_OVERFLOW_ENABLED=true
ASYNC_BUS_OVERFLOW_STORE=database
ASYNC_BUS_SPOOL_DB_CONNECTION=mysql
ASYNC_BUS_SPOOL_DB_TABLE=async_bus_spool_items

ASYNC_BUS_EXTERNAL_ENABLED=true
ASYNC_BUS_EXTERNAL_DRIVER=redis_streams
ASYNC_BUS_EXTERNAL_DEFAULT_QUEUE=default

ASYNC_BUS_DASHBOARD_ENABLED=true
ASYNC_BUS_DASHBOARD_ACCESS=local
ASYNC_BUS_DASHBOARD_LOCALE=de

ASYNC_BUS_API_ENABLED=false
ASYNC_BUS_API_DOCS_ENABLED=false

Full explanation of all keys: docs/configuration-reference.md.

BufferedQueue example

use TimoFrenzel\LaravelAsyncBus\BufferedQueue\Dto\BufferedUpdateDto;
use TimoFrenzel\LaravelAsyncBus\Facades\BufferedQueue;

BufferedQueue::updateDto(
    BufferedUpdateDto::make('search_index', $userId)
        ->withPayload(['model' => 'User', 'id' => $userId])
        ->delay(5)
);

Use BufferedDeleteDto for deletes and BufferedPushDto for deduplicated push-style payloads.

ExternalQueue example

use TimoFrenzel\LaravelAsyncBus\ExternalQueue\Dto\ExternalJobDto;
use TimoFrenzel\LaravelAsyncBus\Facades\ExternalQueue;

ExternalQueue::dispatchDto(
    ExternalJobDto::make('image.transcode', [
        'image_id' => $imageId,
        'source' => $path,
    ])->onQueue('media')
);

Projection example

use TimoFrenzel\LaravelAsyncBus\Facades\Projection;
use TimoFrenzel\LaravelAsyncBus\Projection\Dto\ProjectionUpdateDto;
use TimoFrenzel\LaravelAsyncBus\Projection\Dto\ProjectionDeleteDto;

Projection::update(ProjectionUpdateDto::make('search_index', $userId));
Projection::delete(ProjectionDeleteDto::make('search_index', $userId));

Projection handlers implement ProjectionHandlerInterface. See docs/projections.md.

Common commands

php artisan async-bus:health
php artisan async-bus:inspect
php artisan async-bus:flush search_index
php artisan async-bus:external:work default
php artisan async-bus:projection:verify
php artisan async-bus:projection:rebuild search_index --keys=1,2,3
php artisan async-bus:workers:list
php artisan async-bus:rc-audit

Dashboard and API

Dashboard:

ASYNC_BUS_DASHBOARD_ENABLED=true
ASYNC_BUS_DASHBOARD_ACCESS=local
ASYNC_BUS_DASHBOARD_PATH=async-bus

Dashboard screenshots from the local playground:

Async Bus dashboard overview Async Bus queues dashboard

Async Bus projections dashboard Async Bus failed jobs dashboard

Async Bus metrics dashboard

Protected API:

ASYNC_BUS_API_ENABLED=true
ASYNC_BUS_API_TOKEN=change-me
ASYNC_BUS_API_DOCS_ENABLED=false

OpenAPI files are generated and verified:

php artisan async-bus:openapi:generate
php artisan async-bus:openapi:verify

When ASYNC_BUS_API_DOCS_ENABLED=true, the protected API exposes:

GET /async-bus/api/openapi.yaml
GET /async-bus/api/openapi.json

Release checks

composer pint
composer ci
php artisan async-bus:rc-audit

The RC audit covers code, dashboard routes/views, translations, config, docs and OpenAPI drift.