🎯Laravel Database Seeders: Beyond Dummy Data
How to manage roles, permissions, and master data safely across local, staging, and production environments
Setting up consistent data across environments is one of the most common challenges in Laravel projects. Whether you are onboarding a new developer, preparing demo data for QA, or running automated tests, manually inserting records into the database is error-prone and time-consuming.
Laravel solves this problem elegantly using Database Seeders.
🔰What Is Database Seeding in Laravel?
Database seeding is the process of populating your database with predefined or fake data using PHP classes.
Laravel seeders allow you to:
Insert default records (roles, permissions, admin users)
Generate dummy data for testing
Maintain consistent data across environments
Avoid repetitive manual database setup
Seeders are especially useful in local, testing, and staging environments.
⚙️How to Create a Database Seeder in Laravel
Creating a database seeder in Laravel is straightforward and follows a clear, standardized workflow. Seeders allow you to define database data using PHP code, making your setup repeatable and version-controlled.
🛠️ Laravel provides an Artisan command to generate a seeder.
php artisan make:seeder TransactionStatusSeederThis command creates a new seeder file inside the database/seeders directory.
database/seeders/TransactionStatusSeeder.php🧩 Understand the Seeder Structure
A basic seeder class looks like this:
use Illuminate\Database\Seeder;
class TransactionStatusSeeder extends Seeder
{
public function run()
{
// Seeding logic goes here
}
}Every seeder extends the
SeederclassThe
run()method is executed when the seeder runsAll database insert logic lives inside this method
🧪Add Data to the Seeder
Assume you have a table called transaction_statuses with columns:
codelabelis_active
Now define the seeding logic:
use Illuminate\Database\Seeder;
use App\Models\TransactionStatus;
class TransactionStatusSeeder extends Seeder
{
public function run()
{
$statuses = [
['code' => 'PENDING', 'label' => 'Pending', 'is_active' => true],
['code' => 'POSTED', 'label' => 'Posted', 'is_active' => true],
['code' => 'REVERSED', 'label' => 'Reversed', 'is_active' => true],
['code' => 'VOIDED', 'label' => 'Voided', 'is_active' => false],
];
foreach ($statuses as $status) {
TransactionStatus::updateOrCreate(
['code' => $status['code']],
$status
);
}
}
}Why updateOrCreate()?
Prevents duplicate records
Allows controlled updates to labels or flags
Safe to run in production
Ideal for master data
This pattern is widely used in finance, insurance, and accounting systems.
✍️ Register the Seeder
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
TransactionStatusSeeder::class,
]);
}
}The DatabaseSeeder class is the central entry point for all database seeders in a Laravel application. Whenever you run a seeding command, Laravel starts execution from this class and then calls all registered seeders in the defined order.
Understanding DatabaseSeeder is essential because it controls what data gets seeded, when it gets seeded, and in which environment.
📁 Where Is DatabaseSeeder Located?
Laravel automatically creates this file at:
database/seeders/DatabaseSeeder.phpdatabase/seeders/
├── DatabaseSeeder.php
├── TransactionStatusSeeder.php
└── RoleSeeder.phpThis file exists by default in every Laravel project and acts as the orchestrator for all other seeders.
📄 Basic Structure of DatabaseSeeder
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run()
{
// Call individual seeders here
}
}Key Points
DatabaseSeederextends the baseSeederclassThe
run()method is the starting pointAll child seeders are invoked from here
▶️ How DatabaseSeeder Works
When you run:
php artisan db:seedLaravel performs the following steps:
Bootstraps the application
Loads
DatabaseSeederExecutes the
run()methodCalls all registered seeders in sequence
Executes each seeder’s
run()method
This makes DatabaseSeeder the single source of truth for seeding.
🔹Registering Seeders in DatabaseSeeder
To execute a seeder, it must be registered using the call() method.
class DatabaseSeeder extends Seeder
{
public function run()
{
$this->call([
RoleSeeder::class,
PermissionSeeder::class,
UserSeeder::class,
]);
}
}Why Order Matters
Roles must exist before permissions are assigned
Permissions must exist before user-role mapping
Prevents foreign key constraint errors
🔹Calling Seeders Conditionally
You can control which seeders run based on the environment.
public function run()
{
$this->call([
RoleSeeder::class,
PermissionSeeder::class,
]);
if (app()->environment(['local', 'staging'])) {
$this->call(UserSeeder::class);
}
}This ensures:
Production stays clean
Test users are not created in live systems
🗂️ Grouping Seeders for Better Organization
In large applications, it’s a good practice to group related seeders.
public function run()
{
$this->call([
MasterDataSeeder::class,
AuthorizationSeeder::class,
ConfigurationSeeder::class,
]);
}Each group seeder can internally call smaller seeders.
class AuthorizationSeeder extends Seeder
{
public function run()
{
$this->call([
RoleSeeder::class,
PermissionSeeder::class,
RolePermissionSeeder::class,
]);
}
}This improves:
Readability
Maintainability
Scalability
▶️ Running the Seeder Explicitly via Artisan
php artisan db:seed --class=TransactionStatusSeederRunning DatabaseSeeder Explicitly
Although DatabaseSeeder runs by default, you can explicitly call it:
php artisan db:seed --class=DatabaseSeederThis is useful in:
CI/CD pipelines
Controlled production deployments
Multi-tenant seeding workflows
🗄️Database Seeders: A Game-Changer for Multi-Tenant Applications
In a multi-tenant architecture, a single application serves multiple tenants, but each tenant’s data must remain isolated.
This makes database seeding fundamentally different from a single-database application.
Laravel seeders play a critical role in initializing and maintaining consistent data across all tenants.
🔹 The Core Challenge in Multi-Tenant Seeding
In a normal Laravel app:
One database
One
DatabaseSeederSeed once → done
In a multi-tenant system:
Multiple tenant databases or schemas
Each tenant requires the same base data
Seeding must happen per tenant, not globally
📌 Examples of tenant-specific data:
Roles & permissions
Default users
Configuration settings
Accounting rules
Commission slabs
Feature flags
The Tenancy for Laravel package, along with the Spatie package, helps manage tenant isolation and provides tenant-aware features for Laravel applications.
Tenant-aware Artisan Commands
You can run migrations or seeders per tenant.
Example:
php artisan tenants:migrate
php artisan tenants:seed --class=SomeSeederWithout this, running php artisan db:seed would only affect the central database.
The package automatically switches the database connection and context based on the current tenant.
This makes queries “tenant-aware” without changing your code everywhere.
📝 Seed all tenants with default DatabaseSeeder:
php artisan tenants:seed📝 Seed a specific tenant seeder:
php artisan tenants:seed --class=TransactionStatusSeeder📝 Seed a specific tenant (if supported by package):
php artisan tenants:seed --tenant=1 --class=TransactionStatusSeeder📝Best Practices for Laravel Seeders
✅ Keep seeders small and focused
✅ Use factories for large datasets
✅ Separate master data (roles, permissions)
✅ Use environment checks
❌ Never seed sensitive production data
❌ Avoid running destructive commands in production
⚠️Common Mistakes and Troubleshooting
Seeder not running?
Ensure it is registered in
DatabaseSeeder
Foreign key constraint errors?
Disable foreign key checks temporarily
Ensure correct seeding order
Duplicate records?
Add existence checks before inserting
🌐Real-World Use Cases
Creating default admin users
Seeding roles and permissions
Generating transactions for QA testing
Preparing demo data for stakeholders
Speeding up onboarding for new developers
🧵 Wrapping Up
Laravel Database Seeders are a powerful yet simple tool that can save hours of manual setup and ensure consistency across environments.
When used correctly—with factories, best practices, and environment awareness—seeders become an essential part of any professional Laravel project.
A well-designed seeding strategy is not just about dummy data—it’s about predictable, repeatable, and reliable development environments.



Thank you! Glad you found it useful 😊
Very Detailed discussion on the Laravel Seeder. Good work, keep doing it.