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

Amazon Sqs Messenger Laravel Package

symfony/amazon-sqs-messenger

Amazon SQS transport for Symfony Messenger, with FIFO and fair-queue support, X-Ray trace stamps, receipt-handle handling, and middleware for automatic FIFO group and deduplication IDs. Includes AmazonSqsFifoStamp, AmazonSqsFairQueueStamp, AmazonSqsXrayTraceHeaderStamp, and AmazonSqsReceivedStamp.

View on GitHub
Deep Wiki
Context7

Getting Started

symfony/amazon-sqs-messenger is the SQS transport for Symfony Messenger. In a Laravel app you normally pull it in alongside the Messenger component (it brings async-aws/sqs + async-aws/core with it):

composer require symfony/messenger symfony/amazon-sqs-messenger

Register the transport factory once in a service provider, then build a transport from a DSN:

use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsTransportFactory;
use Symfony\Component\Messenger\Transport\TransportFactory;

$this->app->singleton(AmazonSqsTransportFactory::class);
$this->app->singleton(TransportFactory::class, fn ($app) => new TransportFactory([
    $app->make(AmazonSqsTransportFactory::class),
]));
// config/messenger.php or a dedicated config file
'orders' => [
    'dsn' => env('SQS_DSN', 'sqs://default?region=eu-west-1&queue_name=orders'),
],
'orders_fifo' => [
    'dsn' => 'sqs-fifo://default?region=eu-west-1&queue_name=orders.fifo',
],

Where to look first, in this order:

  1. AmazonSqsTransportFactory — the DSN parser; every query option you can set lives here.
  2. AmazonSqsTransport — wires sender/receiver, implements SetupableTransportInterface (this is what messenger:setup-transports calls to create the queue).
  3. SqsSender / SqsReceiver / SqsConnection — the actual SendMessage/ReceiveMessage/DeleteMessage calls.
  4. AmazonSqsException — has isMissingQueue(), isInvalidParameter(); catch these to distinguish "queue not provisioned" from "bad payload".

First use case — one queue, one worker. Create the queue, dispatch, consume:

php artisan messenger:setup-transports   # or create the queue in Terraform/CDK
php artisan messenger:consume orders -vv

Keep messenger:consume under Supervisor/systemd as a long-running daemon — it is not a queue:work equivalent and does not use Laravel's queue tables, events, or failed_jobs.

Implementation Patterns

Pick this transport over Laravel's native sqs queue driver when you need FIFO semantics, per-message groups, or explicit deduplication. The native driver treats SQS as a simple job feed; this package exposes the SQS concepts directly.

Dispatching with stamps. Behaviour is driven by stamps on the envelope, not by config:

use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\AmazonSqsFifoStamp;
use Symfony\Component\Messenger\Stamp\DelayStamp;

$bus->dispatch(new SyncOrder($id), [
    new AmazonSqsFifoStamp(messageGroupId: 'customer-'.$customerId),
    new DelayStamp(30_000), // ms, SQS caps DelaySeconds at 900s
]);

DelayStamp above 900 000 ms silently degrades — for anything longer, schedule it (scheduler, Step Functions, or a delayed re-dispatch) rather than hoping SQS accepts it.

Wrap the Messenger worker in an Artisan command. Laravel's queue:work knows nothing about Messenger, so you own the loop:

$this->app->make(ConsumeMessagesCommand::class);

A thin command that resolves the transport by name and delegates to Symfony\Component\Messenger\Worker gives you --time-limit, --memory-limit, and StopWorkerOnSignalsListener for free — which is what you want for graceful container shutdowns.

Serializer choice is an integration decision, not a detail. The default PhpSerializer is opaque to other consumers and unsafe across trust boundaries; use Symfony\Component\Messenger\Transport\Serialization\Serializer with Symfony's JSON serializer (or your own Laravel-aware encoder) when non-PHP services (Node, Go, Lambda) read the same queue. Headers are shipped in the x-symfony-messenger message attribute, so non-Messenger consumers must ignore it and read only the body.

Retries and failures are an AWS concern. This transport does not maintain a failed-message table — a nacked message returns to the queue after the visibility timeout. Configure a redrive policy with maxReceiveCount plus a DLQ on the queue itself, and inspect/redrive from there. Optionally catch RejectMessageExceptionInterface in a middleware to delete poison messages rather than letting them cycle.

Local development: point the DSN at LocalStack or ElasticMQ instead of mocking the SDK. It exercises the real code path including attribute serialisation:

sqs://test:test@default/orders?region=us-east-1&endpoint=http://localhost:4566

Keep that DSN in .env.local only — the endpoint option bypasses normal AWS endpoint resolution.

Consumer sizing. Run several messenger:consume processes for throughput; for FIFO queues, parallelism only helps across distinct MessageGroupIds, so shard your group IDs deliberately.

Gotchas and Tips

  • 256 KB hard limit. SqsSender throws when the encoded body plus attributes exceeds it. If payloads can grow, use a claim-check pattern (store the blob in S3, send the key) instead of chasing compression.
  • Visibility timeout is the lease, not a retry timer. If visibility_timeout (default 30s) is shorter than your handler, SQS redelivers mid-processing and you get duplicates and double side effects. Set it to your p99 handler duration, or extend it from inside long handlers. Make handlers idempotent regardless.
  • Keep it above the graceful-shutdown window. stopwaitsecs in Supervisor must exceed the longest in-flight request, otherwise SIGKILL lands mid-ack and the message is redelivered. Since v8.1.8, Symfony holds pending signals until the in-flight SQS request (send/delete) finishes, so a SIGTERM arriving during an acknowledgement no longer aborts the HTTP call — but that protection only covers the request itself, not your handler.
  • Serializer mismatch = poison message loop. If a producer uses PHP serialization and the consumer expects JSON (or vice versa), decoding throws before any middleware can run and the message is redelivered until maxReceiveCount is hit. Always have a DLQ before deploying a serializer change, and ship the change in both directions before rolling consumers.
  • FIFO requires the sqs-fifo:// scheme. Using sqs:// against a .fifo queue fails at send time; the scheme is what makes the transport attach MessageGroupId/MessageDeduplicationId. Deduplication only covers a 5-minute window — don't treat it as exactly-once.
  • Long polling defaults matter. wait_time defaults to 20s, which is correct for cost; a tiny poll_timeout on an empty queue spins CPU. Prefer fewer, longer-polling workers over many short-polling ones. buffer_size controls how many messages a single receive batches — raise it for high-throughput, low-latency-tolerant workloads.
  • Queue provisioning is opt-in. Nothing creates the queue implicitly. Either run messenger:setup-transports in deploy or (better) manage queues via IaC, and let the app fail fast with AmazonSqsException::isMissingQueue().
  • DSN credentials leak into logs and Sentry payloads. Prefer IAM instance/task roles — omit access_key/secret_key entirely and let the SDK chain resolve them. When you must use temporary credentials, pass session_token, and rotate via env not config cache.
  • Debugging: append debug=1 to the DSN to get HTTP-level logging from async-aws, and route the Symfony\Component\Messenger namespace to a dedicated log channel. For "message never arrives", check the SQS console's NumberOfMessagesSent before blaming the transport.
  • Extension points: decorate SqsSender/SqsReceiver, add middleware for correlation-ID attributes, or swap AmazonSqsTransportFactory for a subclass if you need DSN options the package doesn't expose (custom endpoints, per-queue tags). Everything is constructor-injected, so container bindings are sufficient — no forking required.
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.
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus