🧹 Laravel Model Pruning In Laravel 12 — Automatically Clean Up Old Records
Published on November 2, 2025 by Dinesh Uprety
🧹 Laravel Model Pruning in Laravel 12 — Automatically Clean Up Old Records
Keeping your database lean and healthy is essential for performance and maintainability. Over time, tables fill up with old logs, expired sessions, or temporary uploads — data you don’t really need anymore.
Instead of writing custom cleanup scripts, Laravel gives you a simple, elegant solution: Model Pruning. Let’s explore how the Prunable and MassPrunable traits work in Laravel 12, with real-world examples and best practices.
🚀 What Is Model Pruning?
Model pruning is a built-in Laravel feature that automatically deletes old or unnecessary records from your database.
You simply:
- Add the
PrunableorMassPrunabletrait to your Eloquent model - Define which records should be deleted
- Schedule the
model:pruneArtisan command to run periodically
Laravel takes care of the rest. 👌
🧩 Example 1: Auto-Delete Temporary Uploads After 7 Days
Imagine you have a table for temporary file uploads. You want to delete both the file and its record after 7 days.
app/Models/TemporaryUpload.php
namespace App\Models; use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Prunable;use Illuminate\Support\Facades\Storage; final class TemporaryUpload extends Model{ use Prunable; public function prunable() { // Delete records older than 7 days return static::where('created_at', '<=', now()->subDays(7)); } // Called before deleting each record protected function pruning(): void { if ($this->file_path) { Storage::delete($this->file_path); } } // Called after deletion (optional) protected function pruned(): void { \Log::info("Pruned upload #{$this->id}"); }}
Schedule the prune command
// routes/console.php<?php declare(strict_types=1); use Illuminate\Support\Facades\Schedule; Schedule::command('model:prune')->daily();
✅ Done! Every day, Laravel will:
- 🕓 Find uploads older than 7 days
- 🗑️ Delete their files
- 💾 Remove their database records
⚡ Example 2: Pruning Millions of Old Logs (Fast!)
If you’re cleaning up huge tables like activity_logs, you don’t want to delete records one by one.
That’s where the MassPrunable trait comes in — it deletes in bulk.
app/Models/ActivityLog.php
namespace App\Models; use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\MassPrunable; final class ActivityLog extends Model{ use MassPrunable; public function prunable() { return static::where('created_at', '<=', now()->subMonths(6)); }}
💡 Tip:
MassPrunable skips model events and callbacks — it’s faster, but you can’t hook into pruning() or deleted events.
🧠 Useful Artisan Commands
Dry-run first to check what will be deleted:
php artisan model:prune --pretend
Only prune specific models:
php artisan model:prune --model="App\\Models\\TemporaryUpload"
Exclude models from pruning:
php artisan model:prune --except="App\\Models\\User"
🧰 Common Use Cases
- 🗂 Temporary uploads or previews – delete files after a few days
- 📜 Activity / audit logs – keep only the last 6 months
- 🕰 Soft-deleted models – permanently delete after 90 days
- 💬 Notifications or tokens – clean expired entries
- 📦 Large data archives – control database size over time
⚙️ Best Practices
- 🔍 Test first using
--pretendto confirm your query. - 🧑💻 Use
Prunableif you need model events or file deletion hooks. - ⚡ Use
MassPrunablefor very large datasets (no per-model callbacks). - 🧾 Log or monitor how many records get deleted each run.
- 🧩 Combine with
SoftDeletesfor time-based permanent removal. - 🧠 Document your retention policy — know what data you’re deleting.
- 🕐 Schedule during off-peak hours for heavy deletes.
✅ Summary
Laravel’s Model Pruning gives you a clean, framework-native way to handle old data — no custom cron scripts, no manual deletes.
You just:
- 🧩 Define your pruning rule
- 🕓 Schedule the command
- 🧹 Let Laravel keep your database clean automatically
It’s simple, powerful, and perfect for production-grade apps in Laravel 12.
💬 Have you used the Prunable trait yet? Share your favorite use-case or pruning strategy in the comments below!
Senior Software Engineer • Writer @ Laranepal • PHP, Laravel, Livewire, TailwindCSS & VueJS • CEO @ Laranepal & Founder @ laracodesnap