Skip to main content
This is an excellent use case for Server-Sent Events (SSE). It’s much more efficient than polling, as it keeps a single, long-lived HTTP connection open for the server to push updates to the client. Here is a complete step-by-step implementation for your Laravel 10 and Vue 2 application.

The Flow

  1. A user visits a page with the notification component.
  2. The Vue component opens an SSE connection to a specific Laravel route (e.g., /notifications/stream).
  3. The Laravel controller keeps this connection open.
  4. When a new Notification is created in your MongoDB collection, the NotificationObserver fires.
  5. The observer’s created method will write the new notification data to the cache with a user-specific key.
  6. The SseController, in its long-running loop, detects the new cache entry, sends it down the stream to the browser, and then deletes the cache entry.
  7. Vue’s EventSource listener receives the data and updates the UI in real-time.
  8. The “Refresh” button will call a separate, standard API endpoint to fetch all notifications, just like your old polling mechanism.

Step 1: Backend - The Model and Observer

First, let’s set up the model and the observer that will react to new database entries.

1a. Notification Model

I’ll assume you are using the jenssegers/laravel-mongodb package. Your model might look something like this. app/Models/Notification.php

1b. Create the Observer

This is the core of the trigger mechanism. Generate the observer using Artisan:
Now, let’s implement the created method. It will write the new notification to the cache. The cache acts as a fast, temporary message queue between the web request that created the notification and the SSE process. app/Observers/NotificationObserver.php
Note: We use uniqid() to ensure that if two notifications are created for the same user before the SSE loop runs, both are stored in the cache under different keys.

1c. Register the Observer

You must register the observer in a service provider. The best place is EventServiceProvider. app/Providers/EventServiceProvider.php

Step 2: Backend - The SSE Controller and Route

This controller will handle the persistent connection.

2a. Create the Controller

2b. Implement the SSE Logic

We’ll use Laravel’s StreamedResponse to send data without closing the connection. app/Http/Controllers/SseController.php
Important: The cache scanning part is not very performant with the file or database cache drivers. For production, you should strongly consider using redis: CACHE_DRIVER=redis in your .env file. With Redis, you could use Cache::keys($cachePrefix . '*') which is much more efficient.

2c. Define the Route

This route must be protected by authentication middleware. routes/web.php

Step 3: Backend - Manual Refresh Endpoint

This is the standard endpoint that the “Refresh” button will use.

3a. Create the Controller

3b. Implement the Index Method

This method simply fetches all notifications for the current user. app/Http/Controllers/NotificationController.php

Step 4: Frontend - The Vue 2 Component

Now let’s create the Vue component that consumes the SSE stream and provides the manual refresh button. resources/js/components/NotificationBell.vue
You can now use the <notification-bell></notification-bell> component anywhere in your Vue application. You’ve successfully replaced polling with a real-time SSE push system while retaining the ability to manually refresh.