pusher/pusher-php-server
Official PHP library for the Pusher Channels HTTP API. Install via Composer, create a Pusher instance with your app credentials, and publish events or authenticate channels from PHP 7.3–8.4, including Laravel broadcasting.
Architecture fit
pusher/pusher-php-server is a thin, server-side REST client for the Pusher Channels HTTP API — not a framework, not a broker. In a Laravel codebase it is rarely called directly: Laravel's pusher broadcast driver consumes it, so the package typically arrives transitively via laravel/framework. Direct use is justified only for: server-initiated triggers outside the event system, channel-auth endpoints, webhook verification, channel/occupancy queries, and batch fan-out.trigger, triggerBatch, authorizeChannel, authorizePresenceChannel, authenticateUser, webhook, getChannelInfo, getChannels). That makes it easy to wrap behind an internal adapter — which is the right architectural move if we want optionality.host, port, path, useTLS, timeout options plus injectable Guzzle client and PSR-3 logger mean the same SDK can target Pusher cloud, Soketi, or Laravel Reverb (all Pusher-protocol compatible). That single fact materially reduces vendor lock-in risk.Integration feasibility
^7.3), config is env-driven (PUSHER_APP_ID, PUSHER_APP_KEY, PUSHER_APP_SECRET, PUSHER_APP_CLUSTER), and Laravel 8.29+ supports it as a broadcasting backend out of the box. Low integration cost: days, not weeks, for a first vertical slice.laravel/framework requiring this package for its Pusher driver. Treat that field as unreliable and verify against Packagist before using it in any build-vs-buy narrative.Technical risk
trigger throws — in the request path that becomes user-facing latency or 5xxs. There is no built-in durable delivery; durability is our responsibility (queue, retry, persistence).triggerBatch on multi-tenant clusters, per-message payload ceilings, and the documented restriction that a single trigger call cannot mix private-encrypted- and unencrypted channels.Key questions
Stack fit
ShouldBroadcast / ShouldBroadcastNow events, broadcastOn() returning PrivateChannel/PresenceChannel, toOthers() to suppress echo to the originating socket. The SDK's socket_id option is the underlying mechanism — expose it rather than reinventing it.triggerBatch (bulk fan-out), getChannelInfo/getChannels (occupancy dashboards, presence counts), webhook() (signature verification and event ingestion), and authenticateUser if we adopt Pusher's user-authentication feature.Pusher\Pusher, constructed from config, with the injected Guzzle client and our PSR-3 logger attached. Never instantiate the client inline in controllers.Migration path
host/port/useTLS/path options into config from day one and keep an internal Broadcaster interface. That turns a future migration into a config change plus a client-library swap, not a rewrite.Compatibility
^7 and let Composer resolve; validate the Guzzle major version against the rest of the dependency graph early, not at merge time.config:cache picks up env values and that no per-request state leaks into the singleton.Sequencing
timeout.routes/channels.php; add the webhook receiver with webhook() verification.Maintenance
Support
Scaling
triggerAsync/promise chaining for fan-out, move broadcasts to the queue so request latency is decoupled, and prefer socket_id exclusion to avoid feedback loops.user_count/subscription_count queries are useful both as product telemetry and as capacity signals, but they are rate-limited API calls — cache them.Failure modes
timeout explicitly; the default is not a production policy.private-encrypted- and plain channels in one trigger is a documented hard failure; enforce channel naming in code, not convention.Ramp-up
How can I help you explore Laravel packages today?