Publishing Messages
Creating a Message
Section titled “Creating a Message”Create messages with a non-empty type and an array payload:
use Spoolrail\Spoolrail\Message;
$message = Message::make('order.created', [ 'order_id' => 42, 'customer_id' => 17,]);Each message has five public values:
$message->id; // UUID v7$message->type; // "order.created"$message->payload; // The supplied array$message->publishedAt; // null until published$message->transport; // null until received from a transportMessages are immutable. Publishing returns a new instance with a millisecond-precision UTC publishedAt value and no transport context; the original message remains unchanged.
Publishing
Section titled “Publishing”Publish through the default connection:
use Spoolrail\Spoolrail\Facades\Spoolrail;
$published = Spoolrail::publish('orders', $message);Or select another connection:
$published = Spoolrail::connection('partner')->publish( 'orders', $message,);A publisher does not declare or select subscriptions. Every subscription already bound to the topic receives its own copy.
By default, Spoolrail publishes immediately, including inside a database transaction. Enable the Transactional Outbox when a database change and publication must be atomic. With the outbox enabled, the publishing call stores a pending publication without contacting the broker. The transaction commits both the database change and publication, or rolls back both. A separate dispatcher publishes pending publications to the broker.
Publication Retries
Section titled “Publication Retries”By default, Spoolrail retries broker publication failures up to two times, waiting one second between attempts, unless the broker rejects the publication for a permanent reason.
If the broker accepts a message but its response does not reach Spoolrail due to a transient failure, a retry can publish the same message again. Spoolrail deduplicates recent repeats during queue handoff.
Retries can extend how long direct publishing waits during a broker failure. Configure them under spoolrail.publisher_retries.
When the transactional outbox is enabled, the same retry behavior applies when the outbox dispatcher publishes the message. If those retries are exhausted, the publication remains pending for a later scheduled run.
Publication Headers
Section titled “Publication Headers”Pass portable string headers when a publication needs tracing or application metadata outside the logical message:
$published = Spoolrail::publish( 'orders', $message, headers: [ 'traceparent' => $traceparent, 'correlation-id' => (string) $order->id, ],);Use lowercase kebab-case keys and string values. Publications accept up to 10 headers, the AWS SNS-to-SQS portability limit.
Global Headers
Section titled “Global Headers”Register a single application-wide callback when every publication needs common headers, such as correlation identifiers, tenant context, or distributed tracing context (for example, OpenTelemetry). Add it to a service provider’s boot method:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;use Spoolrail\Spoolrail\Facades\Spoolrail;
class AppServiceProvider extends ServiceProvider{ public function boot(): void { Spoolrail::transformHeadersUsing(function (array $headers): array { $headers['application'] = config('app.name');
return $headers; }); }}The callback receives the headers passed to publish and returns the complete header map, so preserve any existing headers that should remain.
Ordering Keys
Section titled “Ordering Keys”Use an ordering key to split a topic into independent groups. Different groups may progress in parallel while messages within each group stay ordered:
$published = Spoolrail::publish( 'orders', $message, orderingKey: "order:{$order->id}",);Use the named fourth argument; headers remains the third argument and does not need an empty placeholder. A key must contain between 1 and 128 printable ASCII characters without spaces.
Drivers use the key as follows:
- RabbitMQ and the
arraydriver accept and ignore the key with no warning. - AWS FIFO keeps messages with the same key in one ordered group and uses one topic-wide group when the key is omitted.
- AWS standard forwards a supplied key to SQS for fair-queue tenant grouping without ordering or deduplication.
- Google Pub/Sub keeps messages with the same key in one ordered lane when ordering is enabled and uses one topic-wide lane when the key is omitted. When ordering is disabled, it still forwards a supplied key without making an ordering promise.
Ordering-capable transports preserve handoff order from the broker to Laravel queue within a group, not across groups or subscriptions. Laravel queue concurrency and retries may change handler execution or completion order. See AWS FIFO Mode and Ordering and Pub/Sub Message Ordering for provider-specific behavior and throughput limits.
Topic Names
Section titled “Topic Names”Topic names must contain between 3 and 251 ASCII characters, begin with a letter, and otherwise contain only letters, digits, hyphens, and underscores.
Valid names include orders, order_events, and orders-v2. Dotted values such as order.created are suitable message types but are not valid topic names.
Payloads and Size
Section titled “Payloads and Size”Payloads must be JSON-encodable arrays. Spoolrail rejects values unsupported by json_encode before publishing.
The complete publication, including headers, may not exceed 256 KiB. MessageTooLargeException exposes the actual byte count and limit. Put large documents and binary data in durable storage and publish a reference instead.
Message Identity
Section titled “Message Identity”Create a new Message for every new logical event. Publishing the same instance again reuses its UUID:
$message = Message::make('order.created', ['order_id' => 42]);
Spoolrail::publish('orders', $message);Spoolrail::publish('orders', $message); // Same message ID