Conditional Migrations in Laravel with the New shouldRun() Method

Feature flags and migrations don't always play well together. Laravel's new shouldRun() method solves this by letting you conditionally execute migrations based on your application's state.
When working with feature flags or phased rollouts, you might want certain database changes to only apply when specific features are active. Previously, this required complex workarounds or manual migration management. The new shouldRun() method provides an elegant solution by allowing migrations to decide for themselves whether they should be executed.
Let's see how it works:
return new class extends Migration
{
public function shouldRun()
{
return Feature::active(Flights::class);
}
public function up()
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('destination');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('flights');
}
}
This migration will only run if the 'Flights' feature is active. If the feature is not active, the migration will be skipped without error, and the migration entry won't be added to the migrations table.
Real-World Example
This feature is particularly useful for phased feature rollouts or multi-tenant applications. Here's a practical example with a SaaS application:
// 2023_05_15_create_analytics_tables.php
return new class extends Migration
{
public function shouldRun()
{
// Only run this migration for environments or tenants
// where the analytics feature is enabled
return config('features.analytics') === true;
}
public function up()
{
Schema::create('analytics_events', function (Blueprint $table) {
$table->id();
$table->string('event_name');
$table->json('properties');
$table->timestamps();
});
Schema::create('analytics_reports', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->json('filters');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('analytics_reports');
Schema::dropIfExists('analytics_events');
}
};
The shouldRun() method is considered for both migrate and rollback commands, ensuring consistent behavior in both directions. If a migration is skipped during migrate, it will also be skipped during rollback.
By leveraging the shouldRun() method, you can create more flexible, context-aware migrations that adapt to your application's needs, making feature flagging and progressive deployment strategies more manageable.
If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter (https://x.com/harrisrafto), Bluesky (https://bsky.app/profile/harrisrafto.eu), and YouTube (https://www.youtube.com/@harrisrafto). It helps a lot!