Database Migrations
The Audiobookshelf server performs database migrations automatically when upgrading or downgrading your server vesion. Database migrations are an internal mechanism used to keep an existing installation’s database in sync with the server version it is running.
Switching between installation methods (e.g., Linux, Windows, Docker) or restoring a database from a different installation method is not a supported process. The database migrations described on this page are not the same thing.
What is a Migration?
A migration is a script that changes the structure of the database. This can include:
- Creating or removing tables
- Adding, modifying, or removing columns
- Modifying indexes for faster searches.
A migration script consists of two parts: an "up" script that applies the changes to the database, and a "down" script that undoes the changes.
Migration Guidelines
When writing a migration for the database, keep the following in mind:
- You must name your migration script according to the following convention:
[server_version]-[migration_name].js. For example,v2.14.0-create-users-table.js.server_versionis the version of the server to run the migration on (usually the next server release).migration_nameis a short description of the changes that the migration makes.
- The script exports two async functions:
upanddown. Theupfunction contains the script that applies the changes to the database, and thedownfunction contains the script to undo the changes. Theupanddownfunctions accept a single object parameter with acontextproperty that contains a reference to a Sequelize QueryInterface object, and a Logger object for logging. A typical migration script might look like this:
async function up({ context: { queryInterface, logger } }) {
// Upwards migration script
logger.info('migrating ...');
...
}
async function down({ context: { queryInterface, logger } }) {
// Downward migration script
logger.info('reverting ...');
...
}
module.exports = {up, down}
- Always export both
upanddownfunctions. - Both the
upanddownfunction must be idempotent (i.e. they are safe to run multiple times on the same database). - Prefer using only
queryInterfaceandloggerparameters, thesequelizemodule, and node.js built-in modules in your migration scripts. You can require other modules, but be aware that they might not be available or change from they ones you tested with. - It is your responsibility to make sure that the down migration reverts the changes made by the up migration.
- Log detailed information on every step of the migration. Use
Logger.info()andLogger.error(). - Test your migrations thoroughly before committing them.
- Write unit tests for your migrations (see
test/server/migrationsfor examples) - You can force a server version change by modifying the version field in
package.jsonon your dev environment (but make sure to revert this change before committing, your PR should not change the version number of the server).
- Write unit tests for your migrations (see
How are migrations run?
On server startup, the server compares the database version to the server version. If these version numbers to not match, migrations are performed to upgrade or downgrade the database to match the server version. Migrations are ran in order (i.e. oldest to newest up migrations if the server version has increased, or newest to oldest down migrations if the server version has decreased).
This means that you can switch between server releases without having to worry about running migrations manually. The server will automatically apply the necessary migrations when it starts.
Migrations scripts are also copied to config/migrations/ when starting the server to ensure the down migrations are avaiable even when running an older version of the server.