Why I Replaced Poetry with uv for almost everything
I used to be that person who would smugly paste a poetry install command into every Dockerfile, CI, etc. I even wrote a blog post last year praising Poetry—it still felt like the obvious default—until one night, after skimming a few posts about uv and waiting on slow builds after every tiny tweak, I installed it out of curiosity. The build that had been taking two minutes finished in fourteen seconds. 🤯
That single data point made me pause. Over the next few weeks I migrated a side project, then a few repository, and eventually every new workflow on my laptop and I started to apply. Today uv is the first tool I install on a fresh dev box—right after git and zsh.
1. What exactly is uv?
Consider uv your all-in-one solution for Python dependency and environment management:
| Need… | What I used before | What I use now |
|---|---|---|
| Resolve & lock dependencies | poetry, pip-tools | uv add / uv lock |
| Create venvs | virtualenv | uv (built‑in) |
| Manage Python versions | pyenv or system installers | uv python |
| Isolated CLI tools | pipx | uv tool & uvx |
| One‑off scripts | A Makefile target nobody remembered | Shebang: #! uv python |
Why does it feel faster? The team rewrote the entire dependency solver in Rust and removed a lot of legacy edge‑cases that only matter to 0.1 % of packages. I rarely dive into the implementation details of python dependency tools, but seeing uv sync finish before the coffee machine warms up still feels like cheating.
TL;DR —
uvtakes the everyday pain points of Python tooling and solves them with a single binary that happens to be lightning‑fast.
2. Five‑minute starter guide
I’ve tested these steps on macOS, Ubuntu, and a Windows. They’re all you need to get productive:
# 1 — install
curl -LsSf https://astral.sh/uv/install.sh | sh # macOS / Linux
# iwr https://astral.sh/uv/install.ps1 | iex # Windows PowerShell
# 2 — create a fresh project
uv init ml-exp && cd ml-exp
# 3 — add your libraries
uv add scikit-learn xgboost optuna matplotlib pandas
# 4 — lock & sync for reproducibility
uv lock && uv sync
# 5 — run code inside the managed venv
uv run python train.py
3. Where uv earned its keep in my MLOps/DevOps life
CI pipelines — Switching from Poetry’s dependency install to
uv synccan reduce each test job by ~6 minutes, adding up to roughly one full engineer-day of CI time saved over 300 runs a week.Dockerized experiments — Swapping
poetry installforuv syncinside Dockerfiles shaved minutes off image builds—suddenly, iterating on model containers felt as fast as editing notebooks.Colleague laptops — New hires clone the repo, run
uv sync, and are ready to code before they’ve even signed in to their email.
4. Multi‑python made boring
Even with lightweight projects, hopping between toolchains is friction-free now:
| Stack | Why it’s pinned | Python |
|---|---|---|
| MLflow 2.22.0 + Kedro 0.19.13 | Production pipeline needs fully versioned data sets and reproducible runs on an image that’s still GLIBC 2.31 | 3.10 |
| LangChain 0.3.25 + ChromaDB 1.0.12 (RAG playground) | Wheels compiled for the 3.11 ABI; keeps vector-store builds lightning-fast | 3.11 |
| Prefect 3.4.3 + FastAPI 0.115.12 (orchestration + micro-service) | Leans on the concurrency and contextvars improvements in 3.12 for async flows | 3.12 |
# one–time interpreter install
uv python install 3.10 3.11 3.12
# slim envs per stack
uv venv pipeline-prod --python 3.10 # MLflow + Kedro
uv venv rag-lab --python 3.11 # LangChain + ChromaDB
uv venv orchestrator --python 3.12 # Prefect + FastAPI
Need to lock a repo? uv python pin 3.11 drops a .python-version file so your IDE, pre-commit, and CI all agree, no more surprise interpreter conflicts between projects.
5. Pro tips & common issues
| Tip | Why it matters |
|---|---|
Commit uv.lock | Your future self (and your CI) will thank you. |
Use uvx for one‑liners | Perfect for ruff or black in pre‑commit hooks. |
uv sync --production | Builds a minimal env excluding dev tools and test libraries. |
| Watch for binary wheels | If a package ships only sdist, uv add will tell you before CI fails. |
⚠️ Minor snags worth knowing:
SSH-based Git dependencies — Resolving a private GitHub package over SSH failed silently until I manually exported:
export GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519'After that,
uvhandled it fine, but the initial error message gave no hint it was SSH-related.No editable installs (
-e) yet —uvdoesn’t supportpip install -e ., which is a blocker if you rely on live reload during local development. You’ll need to work around it with manual symlinks or fall back to pip for now.Slight CLI surprises — If you run
uv pip install ...outside auv-managed venv, it installs into your global interpreter, unlikepip, which often warns or errors. It’s easy to forget you’re not in a managed shell, so double-check where you’re installing.
6. Head‑to‑head speed numbers
| Scenario | uv | PDM | Poetry | pip-sync / pip-compile |
|---|---|---|---|---|
| Warm Installation | 0.1 s | 1.8 s | 0.9 s | 3.6 s (pip-sync) |
| Cold Installation | 1.2 s | 2.1 s | 2.7 s | 7.1 s (pip-sync) |
| Warm Resolution | 0.03 s | 2.0 s | 0.6 s | 1.2 s (pip-compile) |
| Cold Resolution | 0.4 s | 3.2 s | 3.5 s | 3.8 s (pip-compile) |
uv = quickest result in each benchmark; bold values mark where uv beats every other tool by a wide margin.
What each scenario means
- Warm Installation – Re-installing with wheels already cached locally.
- Cold Installation – First-time install on a clean cache.
- Warm Resolution – Updating/locking deps after a previous successful run.
- Cold Resolution – Resolving a lock file on a brand-new machine with no cached metadata.
Where to find the raw benchmark
Check out their GitHub benchmarks here for more details.
7. When to reach for uv, and when not to
uv is a no‑brainer for:
- Heterogeneous data‑science repos where setup time kills flow.
- CI pipelines that pay per minute.
- Teams who secretly hate reading internal Confluence pages about
pyenvhacks.
Hold off if:
- You package a public library and rely on Poetry’s
buildcommand (for now; UV build is on their roadmap). - You need editable installs (
pip install -e) with custom PEP 660 backends. support is experimental.
8. Further reading & watching
- The concise official docs are surprisingly good.
- Astral’s launch post explains the design philosophy.
Final thoughts
Every few years the Python ecosystem gets a ‘why didn’t we have this earlier?’ moment—black, then ruff, and now uv. Swapping it in took a lazy Saturday afternoon and eliminated half a dozen lines from my Makefile. If your workflow still juggles pip, venv, pyenv, and a dash of pipx, give uv an hour. Chances are you’ll save many more.