There's two ideas worth knowing about here. Both are inspired from my background in Ruby on Rails, so I've included a bit about how Rails does it for context:
- In Rails, when you set up a new database, it doesn't expect to run every migration ever, to get the database right. Rails also maintains a single file called
schema.rb
which holds the current, full, up-to-date state of your database (including a list of the names of the migrations that have run to get it up to that point). So when you create a new database, it just reads whatever's in the schema.rb
file, and creates those tables.
Then, rails will run FUTURE migrations on that database, moving forward. But the ones that had run prior to the latest schema.rb
being created - well, you don't need them at all. In fact, once they've run everywhere they need to, you can delete them if you want.
Now, sequelize doesn't do this (though I wish it did!). What you can do, though, is every so often, dump your entire database structure as SQL. Save it as eg. 20170427051240-initial-structure.sql
, in your migrations file, timestamped to be a second after the latest migration that it included. So, now you have something kinda like Rail's scehma.rb
.
The next step is: edit the migration that ran directly prior to that timestamp, so that all it does is imports that entire database structure. Something like this:
'use strict';
module.exports = {
up: function(queryInterface, Sequelize) {
if (!['test', 'ci'].includes(process.env.NODE_ENV)) {
// In all other environments, the database will already have been set up, so
// we don't need to import the full structure
return;
}
return queryInterface.sequelize.query(`
BIG FAT STRING OF SQL GOES HERE.
Note: in my app I've actually got it done table by table,
in separate chained promises, but don't remember why.
`)
}
}
OK. So now you can delete all migrations prior to that one - because that one takes care of everything that would have run prior, anyway.
There's a few considerations, eg. you might want to save 20170427051240-initial-structure.sql
, then wait a month or two, allow another 15 migrations to accumulate, and then do the steps above, so that setting up a new database will import the initial structure as it was a month ago, in the first migration, and then run the most recent 15 migrations, on top of that. That means you always keep a record of the last several migrations, in case you need to roll them back or something.
- Another common practice in the Rails world, which more directly applies to your problem above, is to save a copy of your model in the migration file (ie, a copy "frozen in time", so to speak), and use that copy in your migration, rather than your "real" one, which may be deleted down the track. Of course, you don't have to include a FULL copy of the ENTIRE model with all methods etc - you can remove anything that isn't needed for the specific migration.
This can make your migration files big and a bit messy, but who cares? Migrations aren't edited. They're run once and mostly forgotten. So it doesn't matter if they're a bit messy.
I haven't tried this second approach with sequelize, but it worked well for me with Rails.
Hope some of that's useful!