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

Aws Sns Laravel Package

lab123/aws-sns

A Laravel wrapper for Amazon SNS that simplifies publishing messages to topics and integrating AWS notifications into PHP applications. Configure credentials once and send SNS notifications through a clean, familiar API.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal steps

composer require lab123/aws-sns:^2.0
php artisan vendor:publish --tag=sns   # provider/tag name per README

v2.0.0 is a hard platform bump, so check your app fits before you start: PHP ^8.1, Laravel 10–13 or Lumen 10/11, and AWS SDK v3. If you are on Laravel/Lumen 5–9 you cannot use v2 — stay on ^1.0 (see the lifecycle caveat in Gotchas).

Set credentials in .env — the package is a thin wrapper over aws/aws-sdk-php v3, so it will normally pick up the SDK's standard chain (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION) unless the package's own config keys take precedence. Prefer an IAM role / instance profile in production over static keys.

The package registers a Laravel notification channel (auto-discovered on Laravel 5.5+) plus, typically, a message builder for SMS and for topic publishes. Lumen users must register the service provider manually in bootstrap/app.php and $app->configure('sns').

Where to look first

  1. The CHANGELOG/UPGRADE block for v2.0.0 — the release notes describe a platform break, but confirm whether the channel class name, toSns() signature, or message-builder methods also changed. Don't assume the usage API is untouched just because the notes only mention constraints.
  2. The README usage block — the API surface is genuinely small (one or two channel classes and a message object), and it is the source of truth. Do not infer method names from other SNS notification packages.
  3. The service provider, to confirm the config key name and whether the config file is publishable at all.
  4. Your notifiable model, for routeNotificationFor...() — that's the seam where you decide phone number vs. topic ARN.

First use case

The lowest-friction win is a single transactional SMS: add the channel to a notification's via() array, return the recipient's E.164 number from the notifiable, send to yourself in a staging environment, and confirm delivery. Do that before touching topics — it validates credentials, region, the SDK v3 client and the SMS sandbox in one shot.

The second use case is fan-out: publish a domain event to a topic ARN and let SQS/Lambda subscribers decouple from your app. That's where the package earns its keep, because you avoid hand-rolling Aws\Sns\SnsClient calls and payload shaping in every job.

Implementation Patterns

Upgrading to v2.0.0

Treat this as a dependency-graph migration, not an API migration. Audit it first:

composer why-not lab123/aws-sns 2.0
composer why aws/aws-sdk-php        # find packages still pinning SDK v2

The usual blocker is a secondary AWS package (SES, SQS consumer libs, older league/flysystem-aws-s3-v3) that still requires aws/aws-sdk-php ^2 or ^3.0 <3.x. That conflict is entirely outside lab123/aws-sns. Upgrade those first, or accept that you stay on ^1.0. Also drop any stale php artisan config:cache artifact from the old release — the cached config from v1 will survive the deploy and mask the new defaults.

The notifiable routing contract

public function routeNotificationForSns($notification)
{
    return $this->phone; // E.164, e.g. +14155550123
}

For topics, don't overload the same method with two return types. Either use a dedicated channel class with its own route method, or resolve the ARN inside the notification via config (config('services.sns.topics.orders')). Overloading is the single most common source of "it sent to an ARN that isn't a phone number" bugs.

Notification class shape

public function via($notifiable): array
{
    return [SnsChannel::class];
}

public function toSns($notifiable)
{
    return SnsMessage::create()
        ->message('Your order shipped.')
        ->attributes(['sender_id' => config('app.name')]);
}

Treat the builder as immutable-ish and build a fresh message per notification — reusing a message instance across notifications leaks attributes.

Always queue

Wrap notifications in ShouldQueue (and use a queue worker with retries/backoff). SNS is a network call with TLS handshake latency; sending inline in an HTTP request will show up in your p95. Set tries modestly — SNS 4xx errors such as an invalid phone number are permanent and are not worth retrying. If you need at-least-once fan-out semantics for topics, prefer retrying the job and letting SNS's own idempotency/duplicate tolerance handle the rest, or attach a dedupe key as a message attribute.

Pinning and the AWS SDK v3 boundary

v2.0.0 moves the shared SDK constraint from v2 to v3. That is a transitive break for your whole app: SDK v3 changed client construction, middleware, and some result shapes. If you have direct SnsClient/S3Client calls elsewhere, they need their own upgrade pass — do the package bump and the SDK-wide migration in one PR, not two. Pin lab123/aws-sns:^2.0 and let the SDK float within its minor range.

Topic fan-out pattern

Keep one ARN per environment per concern: orders.created, users.registered. Resolve them through config/services.php so staging never publishes into a production topic. Publish structured JSON in the message body and put the event type in MessageAttributes — subscribers (SQS + Lambda, or SQS + a Laravel worker) can then filter with subscription filter policies instead of consuming and discarding everything.

Testing

Notification::fake();
$user->notify(new OrderShipped($order));
Notification::assertSentTo($user, OrderShipped::class);

Notification::fake() stops the channel from firing, which is what you want in feature tests. For assertions on the message contents, assert on the notification's toSns() return value directly rather than mocking the SNS client. Keep one integration test that hits a real (sandbox) topic behind a separate test suite so CI doesn't depend on AWS.

Integration tips

  • Wrap the channel behind your own SmsSender interface if SMS is business-critical. You get a one-file swap point if the package goes quiet, and it keeps lab123/aws-sns out of your domain code. This matters more now that the package's support window is bound to Laravel 10+.
  • For inbound, this package does not help — receiving SMS/topic deliveries means SQS, HTTP subscriptions, or Lambda. Don't expect webhook handling here.
  • Log the SNS MessageId returned by the send. It's the only handle you have when debugging delivery with AWS support.
  • Bump the package in a feature branch with the full test suite, including any queued-notification tests, since v2 also raises the framework floor to Laravel 10. Running it against Laravel 9 tests will fail at the container level, not at the SNS layer.

Gotchas and Tips

The advisory ignore (v2.0.0's sharpest edge). Laravel/Lumen 10 and 11 carry advisory PKSA-zwc5-qtrz-zm1n with no upstream fix. composer audit in CI will now fail on those versions, and the package README says to ignore it. Do so in your app's composer.json — the package cannot fix an upstream framework advisory:

"config": {
    "audit": {
        "ignore": {
            "PKSA-zwc5-qtrz-zm1n": "No upstream fix for Laravel 10/11; accepted until framework upgrade. Revisit quarterly."
        }
    }
}

Two caveats: the reason-mapped form needs a recent Composer (2.7+), otherwise use a plain list of advisory IDs. And an ignore is a decision, not a fix — put the ticket reference and a revisit date in the string so it doesn't become permanent. The cleanest exit is Laravel 12/13, which v2.0.0 also supports and where the advisory doesn't apply.

Laravel/Lumen 5 users are frozen on ^1.0. The release notes explicitly say 5.x apps stay on ^1.0. That branch is now in maintenance-only territory. If you're on Lumen 5/6/8, plan the framework upgrade before you need an SNS fix or a PHP 8.1+ runtime — you will otherwise be pinned to an SDK v2 line indefinitely.

SMS sandbox. New AWS accounts start in the SMS sandbox: you can only send to verified numbers, and every attempt to an unverified number fails. This is the number-one "the package is broken" report and it has nothing to do with the package. Add destination numbers in the SNS console before you debug anything else.

SMS type defaults to Promotional. Without setting the message attribute AWS.SNS.SMS.SMSType to Transactional, OTPs and alerts can be throttled or delivered at low priority. Likewise AWS.SNS.SMS.SenderID is only honoured in some regions (and is generally unsupported in the US). Set both explicitly at the config layer, not per notification.

Phone format. E.164 only. A leading 00, spaces, or dashes will throw. Normalise with phone / libphonenumber at the model boundary and store the canonical form.

Topic ARN vs. phone number. The channel needs to know which publish path to take. If the routing method can return either, guard it and throw a clear exception on an unrecognised value — a silent fallback to "publish to a phone number as a topic" is very hard to diagnose from CloudWatch alone.

Config caching. If you publish the config, remember php artisan config:cache in deploy — and clear it as part of the v2 upgrade, since a cached v1 config pointing at a staging region is a classic post-deploy incident.

Region matters twice. The SDK region controls both the SNS endpoint and SMS delivery routing. Sending from us-east-1 for EU recipients is legal but may be more expensive or blocked by local regulation. Set region explicitly and don't rely on the SDK default.

Message limits. 256 KB total for a publish, including attributes. Message attribute values cannot be empty strings and cannot be arrays — serialise to JSON. Attribute names are case-sensitive and validated; a bad name throws a ValidationException at publish time, not at build time.

Error handling. Distinguish permanent (invalid parameter, throttled-after-retries, endpoint disabled) from transient. Catch the SDK's AwsException, check getAwsErrorCode() (e.g. InvalidParameter, Throttling, EndpointDisabled), log the code and MessageId if present, and only retry the transient set. If your own code constructs the client directly, re-check that construction against SDK v3 — v3 removed some v2 result/exception conveniences. Failing a queued notification hard is often correct — a dead-letter queue on the job is better than a silent drop.

Debugging path. When something "doesn't arrive": (1) did the SDK call succeed and return a MessageId? log it; (2) is the account out of the sandbox / is the destination verified? (3) check CloudWatch for SMS delivery failures and, if you have it, the SNS delivery logs; (4) for topics, check the subscription's filter policy and the SQS DLQ. Almost nothing is a package bug.

Maintenance risk — improved but not gone. v2.0.0 is a good sign: the maintainers moved to SDK v3 and support through Laravel 13, which is more than many micro-packages do. But it is still a small package with essentially no dependent ecosystem, and the Laravel 10/11 advisory means "supported" and "audit-clean" are not the same thing here. Pin the version, keep an eye on the aws/aws-sdk-php constraint it declares (a narrow v3 range will block future SDK minors), and keep the direct-SDK fallback in mind: for a single send path, app(SnsClient::class)->publish([...]) inside your own small service is maybe 30 lines and removes the dependency entirely. The package's value is convenience, not capability — treat it as a thin adapter, not infrastructure.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings