Migrating to a production application database

Metabase’s application database

The main difference between a local installation and a production installation of Metabase is the application database. The application database keeps track of all of your Metabase data: your questions, dashboards, collections, and so on.

Metabase ships with an embedded H2 application database that you should avoid using in production. The reason Metabase ships with the H2 database is because we want people to spin up Metabase on their local machine and start playing around with asking questions.

If you want to run Metabase in production, you’ll need to use a production-ready application database to store your application data. You can switch from using the default H2 application database at any time, but if you’re planning on running Metabase in production, the sooner you migrate to a production application database, the better. If you keeping running Metabase with the default H2 application database, and you don’t regularly back it up, the application database could get corrupted, and you could end up losing all of your questions, dashboards, collections, and other Metabase data.

The migration process is a one-off process. You can execute the migration script from any computer that has the H2 application database file. For example, if you’re trying to migrate from the H2 database to a setup that uses AWS Elastic Beanstalk to run Metabase with an RDS database as the application database, you can run the migration from your computer instead of trying to cram the H2 file into your Elastic Beanstalk.

Avoid migrating and upgrading at the same time

One important thing here is that the version of Metabase you use during the migration process must be the same. Meaning, the Metabase you use to run the migration command must be the same one that was last used to create or update H2 file, which must be the same version you’ll be using in production. Only after completing the migration should you consider upgrading.

You could also choose to run Metabase on a Metabase Cloud plan, which takes care of all of this stuff for you. If you have an existing Metabase, here’s how you can migrate to Metabase Cloud.

Supported databases for storing your Metabase application data

  • PostgreSQL. Minimum version: 9.4.
  • MySQL. Minimum version: 5.7.7. Required settings (which are the default): utf8mb4_unicode_ci collation, utf8mb4 character set, and innodb_large_prefix=ON.
  • MariaDB. Minimum version: 10.2.2. Required settings (which are the default): utf8mb4_unicode_ci collation, utf8mb4 character set, and innodb_large_prefix=ON.

Go with whichever database you’re familiar with. If you’re not familiar with any of these, or not sure which to pick, go with Postgres.

JAR: How to migrate from H2 to your production application database

You must use the same version of Metabase throughout the migration process.

Metabase provides a custom migration command for migrating to a new application database. Here’s what you’ll do:

1. Confirm that you can connect to your target application database

You must be able to connect to the target Postgres or MySQL/MariaDB database in whatever environment you’re running this migration command in. So, if you’re attempting to move the data to a cloud database, make sure you can connect to that database.

2. Shut down your Metabase instance

You don’t want people creating new stuff in your Metabase while you’re migrating. Ideally, if you’re running the Metabase JAR in production, you’re running Metabase as a service.

3. Back up your H2 application database

Safety first! See Backing up Metabase Application Data.

4. Run the Metabase data migration command

Run the migration command, load-from-h2, using the appropriate environment variables for the target database you want to migrate to.

You can find details about specifying MySQL and Postgres databases at Configuring the application database.

Here’s an example command for migrating to a Postgres database:

export MB_DB_TYPE=postgres
export MB_DB_CONNECTION_URI="jdbc:postgresql://<host>:5432/metabase?user=<username>&password=<password>"
java -jar metabase.jar load-from-h2 /path/to/metabase.db # do not include .mv.db

Here’s an example command for migrating to a MySQL database using Java parameter instead of environment variables:

java -DMB_DB_TYPE=mysql -DMB_DB_CONNECTION_URI="jdbc:mysql://<host>:3306/metabase?user=<username>&password=<password>" -jar metabase.jar load-from-h2 metabase.db

Note that the file name of the database file itself might be /path/to/metabase.db.mv.db, but when running the load-from-h2 command, you need to truncate the path to /path/to/metabase.db.

Metabase expects that you’ll run the command against a brand-new (empty) database; it’ll create the database schema and migrate the data for you.

5. Start your Metabase

Start your Metabase (with the db connection info, but without the load-from-h2 and H2 file migration command), and you should be good to go. For example, if you’re using Postgres, your command to start Metabase would look something like:

export MB_DB_TYPE=postgres
export MB_DB_CONNECTION_URI="jdbc:postgresql://<host>:5432/metabase?user=<username>&password=<password>"
java -jar metabase.jar

You should, however, keep your old H2 file just for safe-keeping, or as a heirloom, or talisman, or whatever.

Docker: how to migrate from H2 to your production application database

You must use the same version of Metabase throughout the migration process.

Metabase provides a custom migration command for migrating to a new application database. Here’s what you’ll do:

1. Confirm that you can connect to your target application database

You must be able to connect to the target Postgres or MySQL/MariaDB database in whatever environment you’re running this migration command in. So, if you’re attempting to move the data to a cloud database, make sure you can connect to that database.

2. Back up your H2 application database

Safety first! See Backing up Metabase Application Data.

If you don’t back up your H2 database, and you replace or delete your container, you’ll lose all of your questions, dashboards, and other Metabase data, so be sure to back up before you migrate.

3. Stop the existing Metabase container

You don’t want people creating new stuff in your Metabase while you’re migrating.

3. Download the JAR

In the directory where you saved your H2 file (that is, outside the container), download the JAR for your current version.

Make sure you use the same version of Metabase you’ve been using. If you want to upgrade, perform the upgrade after you’ve confirmed the migration is successful.

4. Run the migration command

Create another copy of your H2 file that you extracted from the container when you backed up your app db (step 2).

From the directory with your H2 file and your Metabase JAR, run the migration command, load-from-h2. Use the appropriate connection string or environment variables for the target database you want to migrate to. The command would look something like:

export MB_DB_TYPE=postgres
export MB_DB_CONNECTION_URI="jdbc:postgresql://<host>:5432/metabase?user=<username>&password=<password>"
java -jar metabase.jar load-from-h2 /path/to/metabase.db # do not include .mv.db

Metabase will start up, perform the migration (meaning, it’ll take the data from the H2 file and put it into your new app db, in this a Postgres db), and then exit.

You can find details about specifying MySQL and Postgres databases at Configuring the application database.

5. Start a new Docker container that uses the new app db

With your new application database populated with your Metabase data, you can start a new container and tell the Metabase in the container to connect to the appdb. The command will looks something like this:

docker run -d -p 3000:3000 \
  -e "MB_DB_TYPE=postgres" \
  -e "MB_DB_DBNAME=<your-postgres-db-name>" \
  -e "MB_DB_PORT=5432" \
  -e "MB_DB_USER=<db-username>" \
  -e "MB_DB_PASS=<db-password>" \
  -e "MB_DB_HOST=<your-database-host>" \
  --name metabase metabase/metabase

7. Remove the old container that was using the H2 database

If you have your H2 file backed up somewhere safe, go ahead and remove the old container. See Docker docs for removing containers.

Running Metabase application database migrations manually

When Metabase is starting up, it will typically attempt to determine if any changes are required to the application database, and, if so, will execute those changes automatically. If for some reason you wanted to see what these changes are and run them manually on your database then we let you do that.

Simply set the following environment variable before launching Metabase:

export MB_DB_AUTOMIGRATE=false

When the application launches, if there are necessary database changes, you’ll receive a message like the following which will indicate that the application cannot continue starting up until the specified upgrades are made:

2015-12-01 12:45:45,805 [INFO ] metabase.db :: Database Upgrade Required

NOTICE: Your database requires updates to work with this version of Metabase.  Please execute the following sql commands on your database before proceeding.

-- *********************************************************************
-- Update Database Script
-- *********************************************************************
-- Change Log: migrations/liquibase.yaml
-- Ran at: 12/1/15 12:45 PM
-- Against: @jdbc:h2:file:/Users/agilliland/workspace/metabase/metabase/metabase.db
-- Liquibase version: 3.4.1
-- *********************************************************************

-- Create Database Lock Table
CREATE TABLE PUBLIC.DATABASECHANGELOGLOCK (ID INT NOT NULL, LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP, LOCKEDBY VARCHAR(255), CONSTRAINT PK_DATABASECHANGELOGLOCK PRIMARY KEY (ID));

...

Once your database is updated try running the application again.

2015-12-01 12:46:39,489 [INFO ] metabase.core :: Metabase Shutting Down ...

You can then take the supplied SQL script and apply it to your database manually. Once that’s done just restart Metabase and everything should work normally.

Troubleshooting migration issues

Check out this troubleshooting guide.

Thanks for your feedback!

See something that needs fixing? Propose a change.