How do I run migrations for a specific environment in laravel

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering Environment-Specific Migrations in Laravel: A Developer's Guide

Setting up database migrations correctly across different environments—local development, staging, and production—is one of the most fundamental yet often confusing aspects of working with any framework like Laravel. When you encounter issues like receiving "Nothing to migrate" or running against the wrong database schema, it usually points to a misunderstanding of how Laravel handles environment configuration versus migration execution.

As a senior developer, I’ve seen this exact scenario repeatedly. The goal is not necessarily to create separate migration files for each environment (which leads to maintenance nightmares), but rather to ensure that when you run artisan migrate, it executes the correct set of scripts against the database defined by your current environment settings.

Let's break down the issue and establish the correct pattern for managing migrations in Laravel.

Understanding Laravel Environment Configuration

The core confusion often stems from how environment variables, specifically those related to database connection (found in your .env file), interact with Artisan commands.

When you execute artisan migrate, Laravel consults the configuration loaded from the .env file. This file dictates crucial settings like DB_CONNECTION, DB_DATABASE, and APP_ENV. If these variables are missing or misconfigured, or if the database connection defined in the environment doesn't match the expected state of the migrations, you can run into trouble.

Your attempt to use --env=local is the right instinct, but it seems the execution context isn't aligning with what the migration runner expects.

The Correct Approach: Running Migrations Contextually

Migrations are designed to be executed against the database specified by the current environment configuration. To ensure you are targeting a specific environment reliably, focus on setting up the correct connection before running the command.

1. Ensuring Environment Variables are Set

Before executing any migration command, you must ensure your .env file accurately reflects the target environment. For local development, Laravel defaults to using the settings specified in that file (often pointing to the SQLite or MySQL instance defined there).

If you are trying to run migrations on a specific database connection that isn't the default, you need to explicitly tell Laravel which configuration to use during execution.

2. Isolating Execution with --env

The --env flag is designed to switch the entire application context, forcing it to load the configurations associated with that environment (e.g., .env.local, .env.staging).

When you run:

artisan migrate --env=local

Laravel loads the configuration for the local environment. If the local environment is correctly configured to point to the correct database, the migration runner should execute successfully against that specific instance. The "Nothing to migrate" message usually means one of two things: either there are no pending migrations in that specific context, or the connection specified by the context cannot be reached.

If you are still facing issues where migrations seem environment-agnostic, it often points to how your database driver handles schema detection. Remember that Laravel provides robust tools for managing this process, and understanding these underlying principles is key to building scalable applications, just as demonstrated in the guidance provided by laravelcompany.com.

3. Best Practice: Separating Schema Management from Environment Setup

Instead of trying to force environment isolation purely through the migrate command flags, a more robust pattern involves treating migrations as pure code that applies schema changes, regardless of where they are executed.

For complex environments (staging vs. production), it is often better practice to manage environment-specific data seeding or specific post-migration tasks separately, rather than altering the core migration execution flow.

If you need true separation—meaning running a complete migration set against a completely different database instance—the standard procedure involves:

  1. Switching Connections: Ensure your application config is correctly pointing to the target database credentials before running Artisan commands for that specific deployment.
  2. Deployment Pipeline: In CI/CD pipelines, define specific environment variables for each stage (e.g., setting DB_DATABASE=staging_db before running the migration step) ensures consistency across all environments.

Conclusion

The issue you faced highlights the critical relationship between Laravel's configuration layer and its command-line interface. Migrations themselves are not inherently tied to a single environment; they are scripts that operate on data defined by the environment. By carefully managing your .env files and understanding how --env switches context, you can reliably execute schema changes in any specific environment you need. Mastering this separation is essential for maintaining clean, scalable, and predictable Laravel applications.