Moving from Poetry to uv workspaces in 2026
Migrating to uv workspaces offers massive speed gains, such as reducing a 90-second pip install to just 8 seconds. This guide covers common pitfalls regarding workspace naming, dependency resolution, and pytest configurations in monorepos.
For 23 packages from a warm cache, uv takes 0.12 seconds while pip takes 6.6 seconds. In a cold cache test for a Django, Celery, Pandas, and scikit-learn stack, uv finished in 8 seconds while pip took 90 seconds. I am seeing teams migrate because uv replaces five tools: pip, pip-tools, virtualenv, pyenv, and pipx. Since OpenAI acquired Astral in March 2026, uv has become part of standard infrastructure. The tool replaces the need for multiple installers and configuration formats by using a single binary. I find the switch from Poetry to uv simple because uv uses the standard PEP 621 metadata format. While Poetry remains a mature choice for building libraries, uv works as a faster, application-style starter. I see users working with uv version 0.12.12 as of September 2026. This tool manages its own updates and requires no Python dependency for installation.
Workspace Pitfalls
I found that if you name your workspace root the same as a package member, even with package = false set in the pyproject.toml, uv sync refuses to run because it cannot disambiguate the identities of the two members. You must give the root a distinct name. If you try to declare dependencies between members without a [tool.uv.sources] entry, uv sync fails. You must use the workspace = true key to tell uv to resolve the dependency locally.
I often encounter teams trying to unify development environments by moving dev-dependencies from individual package files to the workspace root. They assume uv dependency resolution accounts for all dev-dependencies across all pyproject.toml files in the workspace. However, I noticed that uv no longer installs these dependencies when running uv run in a package folder. This breaks test scripts that rely on pytest. You should keep package-specific dev-dependencies in their own files if you use uv run for local execution.
Another pitfall involves pytest in monorepos. If multiple packages have test files with the same name, pytest’s default import mode fails. This is a common issue when multiple packages in a monorepo contain a file named test_helpers.py. You must add importlib mode to the root pyproject.toml to fix this. Do not add init.py to your test directories to solve this, as that causes a silent bug where pytest runs the wrong tests.
The metadata issue is a significant hurdle for teams using internal PyPI mirrors. When you run uv build to create a wheel for a workspace member, the METADATA file does not always resolve to the correct version boundaries for the package dependencies. This makes publishing workspace members as individual packages difficult. In my experience, this forces teams to manually edit metadata or use path dependencies instead of workspace members. Will the resolver eventually handle these edge cases automatically?
Python version management differs greatly during migration. Poetry relies on pyenv to switch versions, while uv handles Python installations directly. Using uv python install 3.12 allows you to pin interpreters without a separate tool.
CI/CD and Caching
CI/CD speed increases are the most obvious benefit of the migration. A pip install step that takes 2 minutes on every push drops to 10 to 15 seconds with uv, which is a massive improvement. I must handle the cache with care in GitHub Actions. The setup-uv action by Astral defaults to pruning the cache of all downloaded wheels. I set prune-cache to false to ensure that subsequent builds remain fast.
I also use the UV_EXCLUDE_NEWER environment variable to manage tools installed via uvx. This allows me to use a specific date as part of the cache key for GitHub Actions. If I add a new tool to the workflow without bumping the date, uvx fails because I set UV_OFFLINE to 1. This ensures the workflow uses a repeatable set of versions. For production builds, I always use the –frozen flag to install exactly what is in the uv.lock.
| Tool | Resolve Time | Install Time |
| pip | 8.1s | 12.4s |
| Poetry | 6.2s | 9.8s |
| uv | 0.4s | 1.1s |
The speed advantage is massive. On a 47-dependency project, uv resolved dependencies much faster than Poetry. As of September 2026, uv has 2.6 times the GitHub stars of Poetry and 2.8 times its monthly PyPI download volume. I have also observed that uv handles parallel downloads and aggressive caching more efficiently than Poetry’s single-threaded resolver. I recommend teams transition to uv for all new projects to avoid the overhead of the old five-tool stack.