den1n/nova-queues
den1n/nova-queues adds a queue management panel to Laravel Nova, letting you browse pending, running, completed, and failed jobs, retry or delete failures, and monitor queue activity without leaving your admin dashboard.
Reality check first. This package is archived, sits at 12 stars, and predates Nova 4/5. Treat it as a reference implementation you may adapt rather than a dependency you should composer require into production. Before committing, verify it even resolves against your Nova version (composer show laravel/nova); the archived state usually means the constraint file pins an old Nova major.
Minimal path to try it:
composer.json (or vendor the source into app/Nova if the Packagist entry is gone).config/app.php (Laravel <11) or rely on package discovery (Laravel 11). Check for a config/queues.php or similar and publish it with php artisan vendor:publish --provider="Den1n\NovaQueues\NovaQueuesServiceProvider".app/Nova/NovaServiceProvider.php → resources() array.php artisan migrate only if the package ships its own tables — most queue-monitor packages read Laravel's existing jobs, failed_jobs, and job_batches tables instead. Confirm before running migrations.Where to look first:
src/ — the Resource class (likely Queue, Job, or FailedJob) and any Actions/ directory. Actions are where retry/delete/flush behavior lives.README.md and CHANGELOG.md — the changelog date tells you the last Nova version it targeted.First use case: replacing the "SSH in and run php artisan queue:failed" workflow with a Nova page that lists failed jobs, shows the exception, and offers a Retry button. That's the 80% value of any package like this.
Resource registration and navigation. Register the resource with a clear navigation group so it doesn't clutter your default sidebar:
public function resources(Request $request)
{
return [
// ...
\Den1n\NovaQueues\Queue::class,
];
}
Set public static $group = 'System'; (or edit $navigationGroup on the resource if the package supports it) — queue pages are operational tooling, not day-to-day CRUD, and grouping them signals intent.
Gate the resource behind a policy. This is the single most important integration: queue tooling exposes failed job payloads and lets people retry/delete production work. Create a QueuePolicy and enforce it in app/Nova/NovaServiceProvider.php:
Gate::define('viewNovaQueues', fn ($user) => $user->isAdmin());
Then reference it in the resource's authorizedToViewAny or via a Nova tool gate. Never ship this open to all Nova users.
Wrap Nova Actions rather than calling Artisan directly. If the package exposes Retry/Delete/Failed-flush actions, keep them. If you need custom behavior (e.g. "retry all failed jobs for a specific connection"), write a Nova Action that wraps Artisan::call('queue:retry', ['id' => $id]) and return the output in the action's response so operators see what happened.
Pair with Horizon for Redis. This resource is a database-inspection layer; it does not replace queue processing visibility. For Redis-backed queues, run Horizon alongside and use this resource only for the failed-job triage view.
Scope the query to production safety. If the resource exposes a Job model with indexQuery, tighten it to avoid accidentally exposing raw payloads:
public static function indexQuery(NovaRequest $request, $query)
{
return $query->select(['id', 'queue', 'connection', 'attempts', 'failed_at', 'exception'])
->orderByDesc('failed_at');
}
Trim the JSON payload column out of the index — it's what slows these pages down.
Nova version lock-in is the headline risk. An archived Nova package almost certainly declares "laravel/nova": "^3.0" or similar. Nova 4/5 changed field APIs (e.g. Textarea sizing, ->onlyOnDetail(), resource authorization signatures). Expect to fork and patch before it renders on a current install. Budget ~half a day to read the diff between the pinned Nova and yours.
The exception field is huge. failed_jobs.exception stores the full stack trace — often 50–200 KB per row. If the resource dumps it into a Textarea on the index or detail view, pages will crawl with more than a few dozen failed jobs. Force it to ->onlyOnDetail() and consider truncating with a custom field or accessor.
Retry semantics differ by driver. queue:retry pushes the job back to its original connection/queue. If the original queue is saturated or the job's attempts field is already at maxTries, retrying silently drops it. After retrying from the UI, verify the job actually re-entered the queue (SELECT COUNT(*) FROM jobs WHERE ...) rather than trusting the green Nova success toast.
Deleting failed jobs is destructive and irreversible. The payload is your only record of what happened. If you expose a "Flush" action, gate it separately from view access and consider logging the id + uuid before deletion. Some operators will click it thinking it's a page refresh.
failed_jobs grows unbounded. On long-lived apps this table can hold hundreds of thousands of rows. Add pruning (Laravel 8+ allows queue:prune-failed --hours=168 in the scheduler) rather than relying on the UI to stay usable.
Database driver only (probably). If the resource reads from jobs/failed_jobs tables directly, it does nothing for Redis/SQS queues beyond what Horizon or CloudWatch already show. Check the source — if there's no Horizon or Sqs awareness, don't expect it to manage those.
Extension points to prefer over forking: Nova Actions, fields() overrides in a subclassed resource, and a custom indexQuery cover most customization needs without touching vendor code. If you must fork, place the copy in app/Nova or app/NovaQueues, remove the composer dependency, and namespace it under your app so future Nova upgrades stay in your control.
Look for the successor before forking. The Nova ecosystem has several maintained queue/failed-job resources (laravel/nova-queues, community packages, and Horizon's own UI for Redis). Given 12 stars and an archive flag, confirm this package still offers something the alternatives don't before investing in a fork.
How can I help you explore Laravel packages today?