H2 file layout

  • metabase.db.mv.db — main data file
  • metabase.db.trace.db — transaction logs

Pre-migration

uptime && top -bn1 | head -20   # system health
sudo du -sh /metabase.db/        # size check

Size → RDS instance sizing: <500MB small, 500MB–2GB medium, >2GB large.

Backup (stop Metabase first)

H2 is embedded — live backups risk corruption and inconsistent snapshots.

docker stop metabase
sudo tar -czf metabase-backup-$(date +%Y%m%d).tar.gz /metabase.db/
docker start metabase
 
# Verify integrity
sha256sum /metabase.db/metabase.db.mv.db
sha256sum backup/metabase.db.mv.db  # must match

Migration command (critical gotchas)

java -jar metabase.jar load-from-h2 /home/user/backup/metabase.db
  1. JAR version must exactly match the version that created the H2 database — mismatches cause corruption
  2. No .mv.db extension — H2 driver adds it automatically; pass the base path only
  3. No ~ shortcuts — use full absolute paths

PostgreSQL connection config

export MB_DB_TYPE=postgres
export MB_DB_CONNECTION_URI='jdbc:postgresql://ev-prod-aux.cv1se1vuaqur.ap-southeast-1.rds.amazonaws.com:5432/metabase?user=postgres&password=yourpassword'

Use single quotes for passwords with special characters. URL-encode special chars in the URI (!%21, ~%7E, #%23).

Docker run with PostgreSQL

docker run -d \
  --name metabase \
  -p 3000:3000 \
  -e MB_DB_TYPE=postgres \
  -e MB_DB_CONNECTION_URI="$MB_DB_CONNECTION_URI" \
  metabase/metabase