Laravel cookbook · Beginner
Delete old records automatically with prunable models
Tables of logs, sessions and soft-deleted rows grow forever.
Approach
Implement Prunable (or MassPrunable for speed) with a query for rows to delete, clean up related files in
pruning(), and schedule model:prune.
Solution
<?php
// app/Models/ActivityLog.php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Model;
class ActivityLog extends Model
{
use MassPrunable; // one DELETE per chunk, no model events
public function prunable(): Builder
{
return static::where('created_at', '<', now()->subDays(90));
}
}
<?php
// app/Models/Export.php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Support\Facades\Storage;
class Export extends Model
{
use Prunable;
public function prunable(): Builder
{
return static::where('created_at', '<', now()->subWeek());
}
protected function pruning(): void
{
Storage::disk('s3')->delete($this->path); // runs for each model before deletion
}
}
Pitfalls
- Forgetting to schedule
model:prune, so nothing is ever deleted. - Using
MassPrunablewhen files or related records must be cleaned up (it skipspruning()). - Retention periods that conflict with legal requirements; agree on them with the business.
Variations
- Run
php artisan model:prune --pretendto see how many rows would be deleted. - Soft-deleted models can be pruned with
static::onlyTrashed()->where(...).
Further reading: Pruning models
Reference: https://laravel.com/docs/13.x/eloquent#pruning-models
More Laravel recipes
- Authorize actions with policies
- Cache expensive data with stale-while-revalidate
- Call external APIs with timeouts, retries and fakes
- Catch N+1 queries with strict Eloquent mode
- Dispatch events and listeners after the transaction commits
- Issue scoped API tokens with Sanctum
- Make queued jobs reliable with retries, backoff and uniqueness
- Prevent race conditions with transactions and row locks