This pack ships three backends behind one interface so you are never locked in.
But which should you actually *use*? This guide gives you a decision framework,
an honest comparison, and migration notes. Because every backend implements the
same ExperimentTracker interface, switching later is a one-line change — so
optimize for where you are today, not where you might be in two years.
Are you offline, in CI, or writing tests?
└─ Yes → custom (local SQLite). Zero setup, zero network, fully deterministic.
└─ No → Do you need a hosted UI, sweeps, and team sharing with no ops work?
└─ Yes → wandb. Best-in-class dashboards and hyperparameter sweeps.
└─ No → Do you want self-hosted, open-source, and model-registry features
under your own control?
└─ Yes → mlflow. Run your own server, own your data.
└─ Unsure → start with custom, switch when a real need appears.
| Dimension | Local SQLite (custom) | Weights & Biases (wandb) | MLflow (mlflow) |
|---|---|---|---|
| Setup cost | None (a file) | Account + wandb login | Run a server or use mlruns/ |
| Hosting | Your disk | SaaS (cloud) | Self-host or local |
| Network required | No | Yes (or offline mode) | No (local) / Yes (server) |
| Hosted UI / dashboards | No (CLI tables) | Excellent | Good (built-in web UI) |
| Built-in sweeps | Grid/random helpers | Yes (Bayesian agents) | Via plugins |
| Team collaboration | Manual (share the file) | Excellent | Good (shared server) |
| Model registry | No | Yes (artifacts) | Yes (first-class) |
| Cost | Free | Free tier + paid seats | Free (you pay for infra) |
| Data ownership | Total | Vendor-hosted | Total (self-hosted) |
| Best for | Tests, CI, offline, demos | Teams wanting zero ops | Orgs wanting control |
The custom tracker is not a toy — it is the right default in several real
situations:
stay fast and hermetic. This pack's own tests use it.
experiment itself.
Its limits are equally clear: there is no hosted UI (you compare via
format_table/to_markdown), and "sharing" means sharing the SQLite file. When
you outgrow it, the interface makes moving up painless.
Choose wandb when you want a polished, hosted experience with essentially no
operational burden:
run tables your whole team can browse.
config with build_wandb_sweep_config and launch agents.
Trade-offs: it is a third-party SaaS (your run data lives on their servers,
though an offline mode exists), and seats cost money beyond the free tier. Use
mode="offline" on locked-down machines and wandb sync later.
Choose mlflow when you want open-source tracking you control end to end:
(tracking_uri="http://mlflow.internal:5000") or even just a local mlruns/
directory with no server at all.
promotion workflows.
Trade-offs: someone has to run and maintain the server for team use, and the UI,
while solid, is less flashy than W&B's. For many organizations that control is
exactly the point.
hosting. You trade dollars for zero ops.
time for a shared server (a small VM is often enough).
Because all three implement ExperimentTracker, your *training code* never
changes — only how you construct the tracker:
# Local during development...
tracker = get_tracker("custom", db_path="runs.db", project="demo")
# ...W&B when you want dashboards...
tracker = get_tracker("wandb", project="demo", entity="your-org")
# ...MLflow when you self-host.
tracker = get_tracker("mlflow", experiment_name="demo",
tracking_uri="http://mlflow.internal:5000")Better still, select the backend from config so it's an ops decision, not a code
change:
from exp_tracking import load_config, tracker_from_config
tracker = tracker_from_config(load_config("config.yaml"))There is no automated cross-backend *history* migration — runs already recorded
in W&B don't move to MLflow. But because comparison reads through the same
interface, you can point compare_runs at whichever backend holds the runs you
care about. In practice teams run custom in CI and a hosted backend for real
training, which this design supports natively.
1. Start on custom while you prototype — instant, offline, testable.
2. Graduate to wandb when you want dashboards and sweeps without ops, or to
self-hosted mlflow when data control and a model registry matter more.
3. Keep custom in your test suite forever — it is the fastest, most
reliable way to verify your tracking code without external dependencies.
You are not choosing a tracker for life. You are choosing the one that removes
the most friction from your *next* experiment.
Get the full Experiment Tracking Pack and unlock everything.
Get the complete guide with every chapter unlocked, including code samples, diagrams, and best practices.
Access all interactive tools with complete data, all workload profiles, and the full scenario library.
Downloadable source code, configuration files, and working examples from every chapter.
Free updates for life. Every new chapter, tool, and improvement included.