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

Laravel Sqs Queue Json Reader Laravel Package

palpalani/laravel-sqs-queue-json-reader

A Laravel package for reading JSON messages from AWS SQS queues. It helps decode and handle SQS queue payloads in Laravel applications, making it easier to consume JSON-based messages from Amazon Simple Queue Service.

View on GitHub
Deep Wiki
Context7

Getting Started

palpalani/laravel-sqs-queue-json-reader swaps Laravel's default SQS job-payload parser for one that tolerates arbitrary JSON bodies on the queue. You reach for it when messages land in SQS from outside Laravel — SNS fan-out, EventBridge rules, S3 event notifications, CloudWatch alarms, or another service's producer — and Laravel's SqsQueue would otherwise choke trying to unserialize() a payload that was never produced by dispatch().

Minimal path:

  1. composer require palpalani/laravel-sqs-queue-json-reader — 0.6.0 adds Laravel 13.x support, so it now spans the 10/11/12/13 line. Pin nothing until you've run your test suite; 0.x means the minor digit can move under you.
  2. Publish the package config (php artisan vendor:publish --tag=...; check the README for the exact tag) and read it before touching config/queue.php. The keys that matter are the connection name, the region/queue URL/credentials passthrough, and whatever hook maps an incoming JSON body to a job class.
  3. Register the connection in config/queue.php using the package's connector rather than sqs, then point a worker at it: php artisan queue:work <connection> --queue=<name>.
  4. First use case: a single non-Laravel producer writing plain JSON, consumed by one job class. Send one message with aws sqs send-message, run the worker with -vvv, and confirm the job is constructed with the decoded array. Do this before wiring up SNS or a multi-shape producer — it isolates "does the connector work" from "is my payload envelope what I think it is".

Look first at the package's connector + queue classes and any payload-normalisation hook; that's where the actual behaviour lives, and it's the code you'll be patching when a producer changes shape.

Implementation Patterns

One connection per message shape. The package's value is in decoding arbitrary JSON, but "arbitrary" is a lie in production — every producer has a stable schema. Give each shape its own connection and worker (queue:work events-s3 --queue=s3-events, queue:work events-sns --queue=sns-fanout). It keeps failure modes separated and lets you scale and monitor them independently.

Thin adapter, fat handler. Treat the decoded payload as a transport detail. Have the job translate the raw array into a small DTO in its constructor or handle(), then hand off to domain services that know nothing about SQS. When a producer bumps its schema version you edit one adapter, not the business logic.

Unwrap envelopes at the edge. SNS bodies nest the real payload in Message, S3 notifications nest an array under Records, EventBridge wraps in detail. Normalise in a per-connection mapping hook or in the job's handle() opening lines, and validate with a match/throw on unknown shapes so an unrecognised message fails loudly rather than silently no-ops.

Reuse Laravel's retry and failure plumbing. Because these are real jobs on a real connection, $tries, $backoff, $timeout, failed() and the failed_jobs table all behave normally. Set $tries explicitly — a malformed upstream message will otherwise burn the default retry budget and eat visibility timeouts. Add a failed() that records the raw body; you'll need it to replay after an upstream fix.

Test against the payload, not the queue. Assert the job's behaviour by constructing it with a captured real-world body. Keep a tests/Fixtures/ directory of one verbatim message per producer, checked in alongside the code — these are your regression net against upstream schema drift. For integration tests, aws sqs against LocalStack or ElasticMQ in CI covers the delete/visibility behaviour that fakes don't.

Observability. Log correlation IDs from the payload (SNS MessageId, S3 eventTime + key) in the job constructor so a job log line maps back to the producer's record. Without this, debugging a "message didn't process" report is guesswork.

Gotchas and Tips

Deletion after Laravel already deleted (fixed in 0.6.0). Before this release the package could attempt a delete on a message Laravel had already removed — visible as spurious ReceiptHandleIsInvalid / AWS.SimpleQueueService.NonExistentQueue-adjacent errors, occasionally on otherwise-successful jobs, and worse when a job's own logic touched the message. 0.6.0 checks first. If you're pinned below 0.6.0 and see intermittent delete failures on successful jobs, that's the bug — upgrade rather than wrapping try/catch around it.

Laravel 13 support is new in 0.6.0. Bumped by laravel-shift, not hand-written, so treat as "tests pass" rather than "battle-tested". Run your own suite against 13 before adopting; the queue internals this package hooks (SqsQueue, connector registration, Illuminate\Queue\Jobs\SqsJob) are exactly the layer that shifts between majors.

Payload shape is not Laravel's job shape, and that's the point. Don't expect job/data/uuid/attempts keys. Anything reading $job->payload()['data'] from inside the job will break. Use the package's accessor for the raw body, and keep any shared base job class aware that it's running on a foreign-payload connection.

Visibility timeout vs. your job's runtime. With foreign payloads there's no retry_after hint from the producer. Ensure the SQS queue's visibility timeout comfortably exceeds $timeout plus retry budget, or you'll get duplicate concurrent processing of the same message — which, for an idempotent handler, is merely wasteful, and for a non-idempotent one is a data bug. Make handlers idempotent keyed on a producer-supplied ID.

Deletes are the whole contract. A worker that throws before deleting leaves the message to redeliver until it hits the queue's redrive policy — and it will then vanish into a DLQ that someone has to own. Set a redrive max-receive and alarm on the DLQ from day one; this package doesn't add a safety net for unparseable messages.

Unparseable JSON is a distinct failure class. A body that isn't JSON at all (S3 test notifications, control messages) should be rejected deliberately, not surfaced as a mysterious TypeError. Add a guard at the top of the mapping hook that deletes-and-logs, or routes to a dedicated dead-letter path, rather than exhausting retries.

IAM permissions drift. The package may need sqs:DeleteMessage, ReceiveMessage, ChangeMessageVisibility — sometimes GetQueueAttributes. Copying a policy from a standard Laravel-SQS tutorial is usually fine, but check the connector's error handling; denied deletes surface as retry loops, not obvious auth errors.

Extension points before forking. The mapping/normalisation hook and the connector registration are the supported seams. Forking the queue class to handle, say, FIFO MessageGroupId ordering or a nested-batch payload means re-reconciling on every 0.x bump — and this release shows the package is actively changing, so fork cost is real.

Version pinning. Twelve of the thirteen 0.6.0 changes are CI/dependency bumps, which tells you releases are cheap here. Pin ("^0.6", not "^0") and read the diff of each minor before upgrading — pre-1.0, the maintainer is under no semver obligation.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin