Originally published on laravel.learnio.dev — part of the Laravel best practices course. View this lesson on the original site.

In this lesson

Migrations are version-controlled database schema changes. They let your team evolve tables using code, instead of manual SQL steps on each machine.

What a migration is

A migration is a PHP class in database/migrations with two methods:

  • up() applies the schema change,
  • down() reverses it.

Laravel runs migrations in timestamp order and records which ones ran in the database.

flowchart LR
  A[Migration file] --> B[php artisan migrate]
  B --> C[Schema updated]
  C --> D[migrations table records run state]

Why teams use migrations

  • no "please run this SQL manually" messages,
  • same schema across local, staging, and production,
  • clear history of how tables changed over time,
  • safer rollback path when releases go wrong.

Think of migrations as Git commits for database structure.

Create and run a migration

Generate a migration:

php artisan make:migration create_posts_table

Example:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->text('body');
            $table->boolean('is_published')->default(false);
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('posts');
    }
};

Run pending migrations:

php artisan migrate

Day-to-day migration commands

php artisan migrate:status
php artisan migrate:rollback
php artisan migrate:rollback --step=1

Use migrate:status before and after deploys to confirm schema state.

Safe workflow for real projects

  1. pull latest code,
  2. run php artisan migrate,
  3. verify app routes that touch changed tables,
  4. deploy code and migrations together.

Avoid editing old, already-run migrations on shared projects. Add a new migration for each schema change so history stays reliable.

From Laravel best practices — What is Laravel?