Laravel down migrations

I get an email newsletter from Martin Joo every week or so. The newsletters generally have some useful tips around the Laravel framework or sometimes just general development tips. I’ve learned a couple of neat tricks here and there, and will continue to receive.

This morning I received an email with a Laravel ‘tip’ regarding deployment issues to watch out for:

Missing down() method in migrations
If you write a migration but forget about the down() method it can cause some trouble. When a deployment goes wrong and you need to roll back to a previous version it’s crucial to have this process as easy and fast as possible. 

The down method in your migration plays a colossal role in deployment rollbacks. If you miss one, your app will be left in an inconsistent state. The code is reverted to the previous version, but your database still have the new schema. 

Everyone has opinions, of course, and while this might intuitively seem like a good idea, my own experience has been that having ‘down’ migrations overall are just bad. Having the ability to conveniently remove data or drop tables or indexes in production is simply not a good idea. I’ve seen this do more harm than good, and the ‘harm’ is often quite bad.

If you deploy, then *immediately* understand you have to roll back, and you can guarantee that there’s no new data in the upgraded database (new table, new column, etc), a ‘down’ migration to revert that new change might be acceptable, and whatever crisis you were trying to avoid has been avoided.

But, imagine you’ve done a migration to add a new table, to go with a new screen, and that gets deployed. A couple hours later you find a problem. ‘Rolling back’ – including deleting the new table where new screen data was stored – will literally remove data people have just entered. Why do that?

I was a bit surprised that Martin’s ‘down migration’ tip didn’t raise this as a concern to be aware of.

So… how might you handle rollbacks if there’s a problem?

If you put out some new feature, and you need to roll the code back, can you just disable that particular feature? “Feature flags” are a technique to use to surround functionality with checks to determine whether to expose said functionality. Being able to just flip a bit in a database (or edit a config file on production if need be) is generally much safer than more code changes. Laravel 10 now bundles a set of feature flag behaviour, but there are other packages you can use as well.

If you don’t have feature flags in place, before you roll out, think about what steps you’d need to take to get the code back, but keep the new database schema in place. In many (likely most) cases, your old code will work just as well with a new table or column in place, and there’s usually no reason to revert those items. There *can* be, if you’ve got triggers or views or procedures that connect earlier tables with new tables/columns. In cases like that, an actual rollback of the state of the database might actually be necessary, but even then, a ‘down’ migration to revert 100% of everything may not make sense. For example, you may need to disable or delete a trigger, but leave existing data in the new column(s) in place.

In short, ‘down migrations’ offer a simple way to be more destructive than was intended, and without explicit backup/restore steps in place before a down migration, you may unintentionally lose data.

Similar Posts

  • PHP Quality Tools

    Curious about checking out the quality of your PHP project, but don’t know where to start? https://github.com/jakzal/phpqa is a project providing docker images of various tools to help measure aspects of your PHP code. will run the phploc tool on your current folder But… you can alias the tool, then simply run $ phpqa <toolname>…

  • CyclopsMonitor

    I’ve been posting more about this new service over on linkedin, but haven’t posted much here. CyclopsMonitor is a web monitoring service – checking if a web address is up, how fast it responds, if specific content is available, when SSL/TLS certs expire, when domain name expires, and… sending you notifications when problems occur. Currently,…

  • Bad I9 PDF form

    Have been needing to programmatically fill out an I9 PDF, retrieved from gov site. Should be fairly straightforward, right? Well… the field names are… a mess. Field names like topmostSubform[0].Page1[0].U\.S\._Social_Security_Number__Last_4_numbers_[0]topmostSubform[0].Page1[0].expiration_date__if_applicable__mm_dd_yyyy[0] topmostSubform[0].Page2[0].Employers_Business_or_Organization_Address_Street_Number_and_Name[0] and so on make it pretty… not straightforward to create a usable key/value combination to search and replace. But… today, I noticed it got…

  • Identity and habits

    “Your present identity should not constrain your future habits”. For this quote from the audio book “Hello, Habits“. Obviously the book is about ‘habits’, but the phrase could easily have been “Your present identity should not constrain your future self”. In either reading of this, it’s been stuck in my head for while now.  How…

  • Importance of backups

    Well… here we are.  10 years later, and … no backups.  Or… none of the data that’s important. Recently had a drive crash in my main server where this blog is hosted.  Had it happen 2 years ago, but the data was recovered, and I put everything on automatic backups.  Using virtualmin, a great control…

Leave a Reply

Your email address will not be published. Required fields are marked *