Migrate from Pusher to Vask (Laravel). Drop-in host swap.

Vask speaks the Pusher protocol, so a standard Laravel Broadcasting app keeps the pusher connection, laravel-echo, pusher-js, Broadcast events, and channel auth flow. The cutover is credentials plus host.

Migration summary

At a glance

low risk
Type
Drop-in host swap
Typical time
10-15 minutes
Server SDK
pusher-http-php unchanged
Client SDK
laravel-echo and pusher-js unchanged
Auth changes
verify existing /broadcasting/auth
Rollback
restore old Pusher env vars

Files touched

  • .env
  • config/broadcasting.php
  • resources/js/echo.js

Get started

Realtime made simple.

Free Tier: 500K broadcasts/mo and 100 concurrent across unlimited apps. $10/mo when you outgrow it.

Minimal cutover

Save your current Pusher values first. Then change the Laravel broadcast env block. If your app still uses BROADCAST_DRIVER, keep that name and set it to pusher.

BROADCAST_CONNECTION=pusher
-PUSHER_APP_ID=123456
-PUSHER_APP_KEY=abc123
-PUSHER_APP_SECRET=xyz789
-PUSHER_HOST=
+PUSHER_APP_ID=your_vask_key
+PUSHER_APP_KEY=your_vask_key
+PUSHER_APP_SECRET=your_vask_secret
+PUSHER_HOST=wss.vask.dev
 PUSHER_PORT=443
 PUSHER_SCHEME=https
-PUSHER_APP_CLUSTER=us3
+PUSHER_APP_CLUSTER=mt1

 VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
 VITE_PUSHER_HOST="${PUSHER_HOST}"
 VITE_PUSHER_PORT="${PUSHER_PORT}"
 VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
 VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

If your SDK asks for an app id, use the Vask app key. Vask does not issue a separate customer-facing app id.

Rollback

Put the saved Pusher values back, redeploy or rebuild the client bundle if VITE_PUSHER_* values are baked in, and clear config cache if you cache Laravel config during deploy. Rollback is symmetric because no app code or schema changes are required.

Laravel package shortcut

composer require vask/laravel
php artisan vask:install

The installer writes the same Pusher-compatible env values and runs php artisan vask:doctor. Source: github.com/vask-dev/laravel · packagist.

Server publish

Confirm config/broadcasting.php reads the Pusher host from env:

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
        'port' => env('PUSHER_PORT', 443),
        'scheme' => env('PUSHER_SCHEME', 'https'),
        'encrypted' => true,
        'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
    ],
],

If host is hardcoded to a Pusher cluster host, change it to read PUSHER_HOST.

Client subscribe

Confirm Echo reads the Vite env values:

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    wsHost: import.meta.env.VITE_PUSHER_HOST,
    wsPort: import.meta.env.VITE_PUSHER_PORT,
    wssPort: import.meta.env.VITE_PUSHER_PORT,
    forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
    enabledTransports: ['ws', 'wss'],
});

Private and presence channels

Keep your existing routes/channels.php callbacks and /broadcasting/auth route. Public channels, Echo.private(...), and Echo.join(...) should keep the same names and event listeners.

Verify

  1. Deploy the env change to staging.
  2. Confirm the browser opens a WebSocket to wss.vask.dev.
  3. Trigger one Broadcast event and verify the client receives it.
  4. Subscribe to one private or presence channel and confirm /broadcasting/auth returns 200.

Gotchas

  • Stale Vite bundle. Server publishes may hit Vask while the browser still connects to Pusher until the client bundle is rebuilt.
  • Old cluster assumptions. Keep PUSHER_APP_CLUSTER only as a compatibility placeholder; PUSHER_HOST=wss.vask.dev routes traffic.
  • Custom auth route. If you changed /broadcasting/auth, make sure Echo still points at the same route after deploy.
  • Whitespace in secrets. A copied newline in PUSHER_APP_SECRET usually shows up as private-channel 403s.

Where to go next

Can I test the Pusher to Vask cutover in staging first?
Yes. Create a staging Vask app, apply the .env diff there, rebuild the client bundle, and verify public, private, and presence channels before touching production.
How do I roll back to Pusher?
Restore the previous Pusher .env values, rebuild or redeploy anything that embeds VITE_PUSHER_* values, and clear Laravel config cache if your deploy uses it. No event, channel, or database changes are required.
Can I run Pusher and Vask in parallel?
The low-risk path is staging first, then a production credential swap. If you need live parallel publishing, add a temporary broadcaster wrapper that fans out each event to both Pusher and Vask, then remove it after verification.
Do private and presence channels need changes?
Usually no. Laravel keeps using /broadcasting/auth, private- and presence- channel names, and the same Pusher-compatible auth signature. Verify the auth endpoint returns 200 after the credential swap.

Get going

Keep the events. Swap the endpoint. Verify staging, then move the same env diff to production.

Make the switch

Swap the credentials. Keep the events.

Use Vask credentials, keep your existing Broadcast events, and point the Pusher-compatible config at wss.vask.dev.