The Problem

Data‑science teams often spin up Metabase manually, juggling cloud credentials, container builds, and networking. The result is a fragmented setup that is slow to provision and hard to keep in sync with the rest of the ML stack.

What This Does

The repository packages a minimal Metabase deployment that runs on Modal. The core logic lives in app/main.py, where a metabase function builds a Modal container, pulls the Metabase JAR, and launches it. Supporting scripts (bin/install, bin/deploy-modal) automate environment preparation and the Modal deployment command. The README.md walks a user through cloning, installing uv, and invoking the two bin scripts to get a live Metabase instance.

How It Is Wired

Execution starts at the entry point app/main.py. The file defines a single function, metabase, which:

  1. Calls modal.Image.from_dockerhub (via the modal SDK) to create a container image.
  2. Executes an external command (subprocess.run) that runs the java -jar metabase.jar command inside the container.
  3. Performs an outbound HTTP request (using requests) to fetch the Metabase JAR from its public URL.

No other Python modules import app/main.py; the internal import graph contains only app/__init__.py (empty) and app/main.py, so the call chain is linear. The external command and network call constitute the only side‑effects outside the repository. Because the function catches a bare except, any exception from the download or subprocess is silently swallowed, which inflates the blast radius of failures.

The bin scripts are thin wrappers:

  • bin/install creates a virtual environment with uv and runs uv sync based on pyproject.toml.
  • bin/deploy-modal sources the environment and runs modal run app.main:metabase.

No Dockerfile or CI configuration is present, so the build and test steps are not automated beyond the manual uv workflow.

How To Use It

# 1. Clone the repo
git clone https://github.com/moses-y/modal-metabase && cd modal-metabase

# 2. Install uv (if not already installed)
#    Follow https://docs.astral.sh/uv/getting-started/installation/

# 3. Install dependencies and activate the venv
bin/install
source .venv/bin/activate

# 4. Deploy to Modal
bin/deploy-modal

After deployment, open the URL printed by Modal (pattern: https://<profile>--modal-metabase-metabase.modal.run). The Metabase UI will appear and can be configured with environment variables as described in the Metabase documentation.

Real‑World Use

A data‑science team can add this repo to their ML pipeline repo, version‑control the bin scripts, and invoke bin/deploy-modal from a CI job (once CI is added). The resulting Metabase instance can point at the team’s PostgreSQL warehouse, providing a low‑friction analytics front‑end that lives in the same cloud region as the model serving workloads.

Code Health & Issues

  • Medium – Broad exception handling – app/main.py uses a bare except, swallowing all errors.
  • Medium – Enable Dependabot or Renovate – pyproject.toml is the only manifest; no bot is configured to keep dependencies up‑to‑date.
  • Medium – Outbound request lacks timeout – The requests.get call in app/main.py has no timeout= argument, risking hangs.
  • Medium – No test suite – Repository contains no tests/ directory or test files.
  • Medium – No CI pipeline – No .github/workflows/ or other CI configuration.
  • Medium – No LICENSE file – Legal reuse terms are undefined.
  • Medium – No lockfile – uv.lock is present but not referenced; pyproject.toml lists modal >=0.72 while the current major is 1.5.4, leaving the project a major version behind.

The Bottom Line

The repo delivers a quick‑start Metabase on Modal with minimal code and clear deployment scripts, making it suitable for proof‑of‑concepts or internal demos. However, the lack of tests, CI, proper exception handling, timeout safeguards, and up‑to‑date dependency management limits its readiness for production use. Teams should treat it as a scaffold and augment it with testing, CI, licensing, and tighter error handling before adopting it in a critical workflow.