RealWorldDev's avatar

Upgrading Laravel 9 to 10 deleted database data

Hello all

I've just completed a Laravel upgrade from version 9 to 10. I followed the guide and ran composer update and everything ran though ok. I then started to test the application to make sure everything was working but couldn't log in. Thinking I was going mad, I opened TablePlus to check I was using the correct email address to sign in with but the users table was empty. I checked all the tables and there was no data in them at all. The only table that has data is the migrations table.

It's almost as if the update procedure has run a migrate:fresh. All tables are there, but all the data has gone. Thankfully, this was just on local but obviously I'm now worried about running this on the production environment (I will obviously take backups when I do).

Is there something I'm missing with all this? This particular project started on version 7 and that upgrade to version 8 never did this. Other projects I've updated haven't done this either. Anyone else seen this?

By the way the project is an API project so no views. The front end is an Angular app. I use Herd for my local setup. Just thought I'd add this for info.

Thanks all!

0 likes
10 replies
LaryAI's avatar
Level 58

It sounds like your database tables were dropped and recreated during or after the upgrade, which would explain the missing data (and only the migrations table retaining data). This situation most commonly happens if a command like php artisan migrate:fresh or php artisan db:wipe was run, either directly, through a post-update script, or as part of an automated process (for example, some test suites or IDE integrations).

Here’s what might have happened and how to avoid it:

Possible Causes

  1. Accidentally Running migrate:fresh or Similar

    • Sometimes developers run commands to ensure migrations are up-to-date, but migrate:fresh drops all tables and re-runs all migrations, resulting in an empty database except for the migrations table.
  2. Test or Post-Install Scripts in composer.json

    • Check if there are any "post-update-cmd" or similar hooks in your composer.json that might run destructive database commands.
  3. Environment Configuration Switched

    • Ensure that your .env points to your development database, not your production one, and that it didn’t temporarily point to a blank/testing database.
  4. Database Testing (php artisan test)

    • If you ran tests and your phpunit.xml is configured to use your development DB without a separate DB_CONNECTION, the testing process could have wiped your local DB.

How To Prevent This

  • Never run destructive commands (migrate:fresh, db:wipe) on production without a full, tested backup.
  • Always check your .env before running migrations/commands post-upgrade.
  • Use a separate database for testing! Make sure your .env.testing or phpunit.xml does not point to your development or production database.
  • Back up your database before any major upgrades (even on local).
  • Review composer scripts in composer.json:
    // Check for anything unexpected
    "scripts": {
        "post-update-cmd": [
            // Any database commands here? If so, consider removing or making them safer!
        ]
    }
    

Recovery

Since this was your local database, hopefully, you have a backup or can repopulate the database with seed data. Unfortunately, without a backup, the data is likely unrecoverable after the fresh migration.

Summary

Upgrading Laravel does not delete your data. Laravel’s core upgrade (Composer update and dependency changes) will never drop or truncate tables. Only running migration-related Artisan commands like migrate:fresh, db:wipe, or automated scripts (explicitly or implicitly) will do this.

Before upgrading production:

  1. Take a full database backup.
  2. Test your upgrade locally and on staging, ensuring no unintended table drops.
  3. Avoid running unnecessary destructive Artisan commands.

Example Safe Update Process

# Backup your database (important!)
php artisan migrate      # Runs only new migrations, keeps data
composer update          # Updates dependencies
# Do NOT run migrate:fresh unless you are okay to lose all data!

If you need to run fresh migrations, always double-check that your .env uses the intended database.

If you need further help auditing your commands or configurations, post your composer scripts and a list of exactly what commands you ran, and I’ll help you spot the problem!

martinbean's avatar

It's almost as if the update procedure has run a migrate:fresh.

@realworlddev Well that completely depends on what steps you’ve actually taken to upgrade. We have no idea what commands you have or haven’t ran as part of the upgrade, but Laravel does not just randomly truncate tables and their rows.

How were you running the application locally? As if it was in something like a Docker image, and you’ve destroyed and re-built the image, then that may account for the data disappearing.

RealWorldDev's avatar

Thanks for the swift reply Martin.

I only ran one command as part of the upgrade which was 'composer update'. I had gone through the composer.json file changing version numbers that I needed to change that were listed in the official update guide, then ran the command. Everything seemed to work fine.

I use Laravel Herd to run everything locally so no Docker image. I've gone back through everything that was output to the terminal and there is nothing there out of the ordinary.

The only post-update-cmd in the composer file is '@php artisan vendor:publish --tag=laravel-assets --ansi --force' which resulted in 'No publishable resources for tag [laravel-assets].' being output but that's just standard. I've not run any other scripts at all.

I'm completely baffled. Just not seen this before.

Snapey's avatar

maybe you project was using sqlite before?

RealWorldDev's avatar

It's a mysql database and has been for the last 3 years. I ran the upgrade on the staging environment (hosted on AWS and uses Forge and I did plenty of backups before doing it!) and it all worked as expected.

The only thing that's different from all updates I've done previously is that I'm now using Laravel Herd for local development. I'm not saying it's something Herd is doing but when I compare from previous updates, that's the only difference. I do have another project that needs updating so I'll see how that behaves.

automica's avatar

providing you have your APP_ENV=production, you wont be able to run migrate:fresh via artisan without it nagging you.

RealWorldDev's avatar

Yup, and I obviously have that for the production app. This happened in my local development environment so it's not set to that. Obviously with it being my local environment it's not a major disaster but still wouldn't like it to do that.

automica's avatar
Level 54

I've had it before when a cache has got stale, and my running my tests (which do use refreshDatabase trait) cleared my local dev tables not my test database.

Perhaps thats what caused your issues?

I ran artisan php artisan optimize:clear which cleared up the caches and sorted the issue for me.

1 like
RealWorldDev's avatar

That's it! That is exactly it. I did indeed run some tests on a feature I had added just before doing the upgrade.

Thank you so so much. This community is fantastic!

1 like
martinbean's avatar

@realworlddev Going forward, never run the optimize or any caching commands outside of your production environment. Laravel did add a Composer command to clear the cache and run tests a few months ago, but it shouldn’t be needed as you shouldn’t be caching your configuration locally in the first place.

1 like

Please or to participate in this conversation.