Skip to main content
← All use cases

Monitoring event:clear in Laravel Production

php artisan event:clear looks like cleanup. It deletes bootstrap/cache/events.php so Laravel will auto-discover listeners from service providers on the next request. That is the right thing to do during development, but in production it is the first half of a two-step operation that leaves your event system running in a slower, potentially inconsistent state if the second half never finishes.

The trouble starts when a deploy script clears the event cache, then fails during event:cache. Production is now running without its cached event-to-listener map. Every request that fires an event goes through auto-discovery, scanning providers and building the listener list from scratch. Boot time goes up, and if you deploy across multiple servers, one node may rebuild its event cache while another stays cleared. Monitoring event:clear turns a silent gap into a deploy signal you can check.

How event:clear works

When you run:

php artisan event:clear

Laravel calls Illuminate\Foundation\Console\EventClearCommand, which deletes the cached event file at bootstrap/cache/events.php. That is the only thing it does. No rebuild. No validation. It removes the cache so the framework reads service provider registrations on every boot instead.

Most production deploy scripts pair it with event:cache:

php artisan event:clear
php artisan event:cache

If the first step succeeds and the second fails, your app is live but running without its event cache. Every event dispatch now has to scan providers to find listeners. The app keeps working, but the deploy script logs exit code 0 because event:clear returned zero.

The risk is not that events stop firing — they keep working. The risk is that performance degrades silently across multiple servers, and nobody notices until someone traces a slow request to the extra provider scans happening on every event dispatch.

Common failure modes

The cache is cleared but never rebuilt. A deploy script clears the old event cache, a later step fails, and the script either stops or carries on. Production now runs auto-discovery on every event. This is the most common event:clear failure in production because the app never crashes, and without a monitor the cleared state can persist across multiple deploys before anyone spots the pattern.

A rolling deploy creates mixed cache states. In a multi-server setup, one node may clear its event cache, another may still hold the old cached events, and a third may have rebuilt with the new release. A listener added in the latest deploy works on the server that already rebuilt its cache and is missing on servers that cleared but did not rebuild. Users see event-driven features that work on some requests and not others.

Permission errors leave the old cache in place. If the deploy user cannot write to bootstrap/cache, event:clear may fail silently without deleting the file. The app keeps serving the old cached event map. A new listener registered in the release never fires in production, and the deploy looks successful because no command crashed.

One server clears while others do not. If you deploy to multiple hosts and only one runs event:clear before the code sync finishes, that host uses auto-discovered listeners from the new release while the others serve cached listeners from the previous release. Listener registration differs between servers, making event-related bugs hard to reproduce.

Building visibility into event:clear

Treat event cache clearing as a deploy event that needs verification. Fail the deploy script immediately if either step doesn’t leave the expected cache state:

#!/usr/bin/env bash
set -euo pipefail

cd /var/www/current

php artisan event:clear

# Confirm the cache file is gone
test ! -f bootstrap/cache/events.php

php artisan event:cache

# Confirm the rebuild actually produced a file
test -s bootstrap/cache/events.php

That catches the command failing on the node running the deploy. It does not catch a node that never ran the deploy step, or a rebuild that failed silently after the clear succeeded.

For a lightweight verification step:

php artisan event:clear
php artisan event:list --event=App\Events\SomeEvent

The second command forces Laravel to boot and discover listeners from providers. If the event map changed unexpectedly — a listener was dropped during the cache rebuild or a provider failed to load — this is where you see it.

Detecting when event:clear fails

Check three things:

  1. Did the file actually get deleted? test ! -f bootstrap/cache/events.php after the command catches silent permission failures where the command reports success but the file still exists.
  2. Did the command run on every server? Query the health endpoint below per host to see which nodes reported the expected state.
  3. Did the rebuild follow? Without confirming event:cache afterward, the cleared state persists and your app runs uncached.

A quick endpoint on each server shows the current event cache state:

Route::get('/_deploy/event-status', function () {
    return response()->json([
        'host' => gethostname(),
        'release' => trim(@file_get_contents(base_path('REVISION'))),
        'events_cached' => file_exists(base_path('bootstrap/cache/events.php')),
        'events_cache_mtime' => file_exists(base_path('bootstrap/cache/events.php'))
            ? filemtime(base_path('bootstrap/cache/events.php'))
            : null,
    ]);
})->middleware('auth.basic');

Call this after every deploy. If one host reports events_cached: false when others report true, that server needs attention before it can serve traffic safely.

Quick setup with Crontinel

Wrap the deploy-window verification above in a scheduled command:

// routes/console.php
Schedule::call(function () {
    if (! file_exists(base_path('bootstrap/cache/events.php'))) {
        throw new RuntimeException('event cache missing - clear ran without a rebuild');
    }
})->everyFiveMinutes()->name('event-cache-state-check');

Crontinel’s package hooks into ScheduledTaskStarting, ScheduledTaskFinished, and ScheduledTaskFailed automatically once installed - no ping URL or config needed. Create a Cron monitor for event-cache-state-check with an alert window that matches your deploy cadence.

If you already monitor the config cache pair (config:clear and config:cache), the same pattern applies here for the event system.

If you already monitor the config cache pair (config:clear and config:cache), adding event:clear fills the same gap for your event system. The pattern is identical: cleared state is not inherently dangerous, but an uncleared cache or a cleared-but-unrebuilt state causes the same class of hard-to-reproduce bugs.

See also

Start monitoring in minutes

Free for one app. No account needed to install and test locally.

composer require crontinel/laravel
php artisan crontinel:install
Get early access