Skip to content
Dashboard

What is the uv Python package manager?

uv is an open source Python package and project manager from Astral. It combines dependency installation, virtual environments, and Python version management in one Rust-based tool, so teams can manage a project without assembling a separate tool for each job.

Vercel uses uv for Python builds and reported 30 to 65% faster builds after adopting it. Results vary with the dependencies and cache available to each build.

Key takeaways:

  • uv is a Python package and project manager from Astral that replaces pip, pip-tools, pyenv, and virtualenv with one tool.

  • Its Rust implementation combines conflict-aware resolution, selective metadata downloads, and a shared package cache to reduce installation work.

  • The biggest speedups need a warm cache, so they depend on keeping that cache between builds.

  • uv installs Python packages from the Python Package Index (PyPI) and other indexes, including wheels with native code. System libraries that those packages do not bundle need separate installation.

  • uv's lockfile, uv.lock, is uv-specific, and uv export converts it when another tool needs a standard format.

Copy link to headingWhat is uv and what does it replace?

uv is an open source tool for managing Python projects, written in Rust by Astral, the company behind the Ruff linter. It launched in 2024 as a drop-in replacement for pip and pip-tools, then grew into a full project manager with its own lockfile later that year.

The uv pip interface lets a project switch installers before adopting uv's project commands. Check its pip compatibility differences, especially configuration files and package-index selection, before replacing an existing install step.

Copy link to headingHow uv's commands map to existing tools

Each job in a conventional Python toolchain maps onto a uv command:

Capability

uv command

What it replaces

Install dependencies

uv pip sync or uv sync

pip, pip-tools

Project management with a lockfile

uv init, uv add, uv lock, uv run

Poetry, PDM

Python version management

uv python install

pyenv

Isolated tool installs

uv tool install or uvx

pipx

Single-file scripts with inline dependencies

uv run with inline script metadata

a hand-built virtualenv per script

Monorepo workspaces

workspace tables in pyproject.toml

one Poetry project per package

Vulnerability scanning

uv audit, in preview

pip-audit

Build and publish

uv build and uv publish

build, twine

In a uv workspace, each member has its own pyproject.toml and all members share one uv.lock. Dependencies resolve together, which suits related packages that can use compatible versions.

Copy link to headingWhy Python teams are switching to uv

Speed is the headline, though it isn't the only reason developers switch. Three properties do most of the work:

  • Astral reports 10 to 100 times faster package operations than pip. The gain depends on the workload and cache state.

  • The universal uv.lock records dependencies across supported Python versions and platforms. Environment markers select the applicable packages during installation, allowing macOS development and Linux builds to share a lockfile.

  • uv python install downloads supported Python interpreters as part of the same project toolchain.

Of the three, speed varies most from project to project, because it depends on which of uv's design decisions a given install gets to use.

Copy link to headingDesign decisions behind the uv package manager's speed

Dependency installation can involve resolution, metadata retrieval, downloads, and unpacking or building packages. Existing lockfiles and cached artifacts let uv skip some of that work. Its implementation also reduces the cost of the work that remains.

Copy link to heading1. Native startup

uv starts as a compiled Rust binary. Python-based installers first load an interpreter and their own modules, so native startup can help with short, repeated commands. Source builds may still invoke a Python build backend, and their cost can outweigh the installer's startup time.

Copy link to heading2. PubGrub dependency resolution

uv uses the Rust implementation of PubGrub to select compatible package versions. When it encounters a conflict, it records the incompatible choices and backtracks with that information, avoiding the same failed combination later.

Those recorded conflicts also help explain why a resolution failed. Within uv's resolution process, loading package metadata is usually the slowest part, even when the metadata is cached.

Copy link to heading3. Package metadata without full downloads

For a wheel, the packaged ZIP archive contains metadata describing its dependencies. uv can read that metadata during resolution without downloading the entire wheel. It tries progressively larger requests:

  1. Request the METADATA file directly from the index, using the static metadata endpoint defined by Python Enhancement Proposal (PEP) 658.

  2. Failing that, issue an HTTP range request for the zip central directory at the end of the wheel, read the offset of the metadata file, and fetch that byte range.

  3. Only if both fail, download the full wheel.

Metadata-only requests save more bandwidth for large wheels. uv still needs the selected artifact for installation unless it is already cached, but it can reject unsuitable candidates without downloading their full contents.

Copy link to heading4. Parallel downloads into a shared global cache

uv allows up to 50 concurrent downloads by default and stores reusable artifacts in a shared cache.

When installing cached wheels, uv defaults to copy-on-write clones on macOS and Linux and hardlinks on Windows. These methods reduce duplicate data where the filesystem supports them; copying remains necessary when linking is unavailable.

In Astral's 2024 launch benchmarks, uv resolved and installed Trio's dependencies 8 to 10 times faster than pip and pip-tools without a cache and 80 to 115 times faster with a warm cache.

Warm-cache installs reuse artifacts from earlier runs. Fresh containers and continuous integration (CI) jobs that do not restore a cache must fetch them again, so measure your own workflow with the cache conditions it will use in production.

Copy link to headingWhen to use uv instead of pip, Poetry, or conda

uv suits teams that want installation and project management in one tool. Existing CI conventions, lockfile requirements, and dependencies outside the Python packaging ecosystem can make other tools a better fit:

Tool

Main workflow

Locking and portability

uv

Install Python, manage projects and environments, build and publish packages

Universal uv.lock; exports to requirements.txt or pylock.toml

pip

Install packages from PyPI and other sources into a chosen environment

Experimental pip lock writes pylock.toml for the current Python version and platform

pip-tools

Compile dependency declarations and synchronize an environment

Pinned requirements files; compile for each target environment that needs a different resolution

Poetry

Manage projects and environments, build and publish; experimental Python installation

poetry.lock records versions and markers; the export plugin supports requirements and pylock.toml

conda

Manage Python and non-Python packages from conda channels

Portable environment specifications and multi-platform lockfile tooling; pip can supply additional PyPI packages

Both uv and Poetry use environment markers to support cross-platform dependencies. Neither lockfile guarantees that every target has a compatible binary or all the system libraries a package needs.

For example, uv can install CUDA-enabled PyTorch wheels. Conda can manage non-Python packages alongside Python dependencies. OS packages or a prepared container image can supply other required libraries.

Copy link to headingHow to adopt uv in a Python project

In a uv project, commit pyproject.toml for dependency declarations and uv.lock for resolved versions. For a pip-tools workflow, compile declarations from requirements.in into a pinned requirements.txt.

Copy link to headingStart a new project with uv init

uv init --no-package creates pyproject.toml, .python-version, README.md, and a starter main.py. Select Python 3.12 during initialization so the version pin and project's minimum Python version agree:

uv init --no-package --python 3.12 my-service
cd my-service
uv add fastapi
uv add --dev pytest
uv run pytest --version

The first dependency operation creates .venv/ and uv.lock. uv run uses that project environment without a separate activation step. Once you have added tests, run them with uv run pytest and commit the lockfile alongside pyproject.toml.

Copy link to headingMigrate a requirements.txt project without moving pins

For a pip-tools project, requirements.in contains direct dependency declarations and requirements.txt contains the tested pins. After initializing the uv project, run uv add -r requirements.in -c requirements.txt to retain those versions as constraints. Compare the generated lockfile before committing the migration.

Projects with separate pins for multiple platforms need the platform-specific migration steps to preserve their environment markers.

To keep the requirements-file workflow, run these commands for the same target environment as the existing pins:

uv venv
uv pip compile requirements.in -c requirements.txt --output-file requirements.txt
uv pip sync requirements.txt

The pip interface retains your requirements files while using uv's resolver and cache. Teams can keep this workflow if they do not need uv's project commands.

Copy link to headingMigrate a Poetry project with migrate-to-uv

The community-maintained migrate-to-uv tool converts Poetry metadata and dependency groups into uv-compatible project settings. Running uvx migrate-to-uv also generates a uv.lock using the versions in an existing poetry.lock.

For everyday installs, uv sync removes packages outside the selected dependency set. uv sync --inexact retains extra installed packages, matching that aspect of poetry install. The following commands cover common operations:

Poetry

uv

poetry install

uv sync --inexact

poetry add pkg

uv add pkg

poetry update pkg

uv sync --upgrade-package pkg

poetry run cmd

uv run cmd

Review the converted version constraints and dependency sources, then run the project's tests in the new environment. The migration also translates Poetry's caret syntax into standard version specifiers.

Copy link to headingFail CI builds when uv.lock drifts

Use uv sync --locked in CI to fail when pyproject.toml and uv.lock disagree. --frozen uses the existing lock without checking the project declarations, so reserve it for workflows that validate the lockfile separately.

If CI uses GitHub Actions, pin both uv and the setup action. Since setup-uv v8.0.0, releases use immutable full-version tags instead of moving major or minor tags. Use a full release tag or commit SHA; astral-sh/setup-uv@v8 does not resolve.

Copy link to headingCache the dependency layer in Docker

Install dependencies in a separate Docker layer before copying frequently changing application code. uv's Docker example first uses uv sync --frozen --no-install-project with the lockfile available, then copies the project and runs uv sync --locked to validate and install it.

Set UV_LINK_MODE=copy when the BuildKit cache mount and target environment use different filesystems to copy files without link-fallback warnings.

Copy link to headingHow Vercel runs uv for Python teams

Vercel provides the Python installer and build-cache handling. Your repository still defines the dependencies and supported Python version that those builds use.

Copy link to headinguv as the default installer on every Python build

Vercel uses uv by default for Python builds, so adopting it locally does not require a custom installer command on Vercel.

The Python runtime accepts pyproject.toml with or without uv.lock, a requirements.txt, or a Pipfile paired with Pipfile.lock. Commit the resolved dependency file used by your deployment workflow.

Copy link to headingReusing the build cache

Vercel restores an available build cache before installation. Reusable dependencies can then avoid a fresh download, although cache misses and changed dependencies still require work.

Cache reuse does not predict a fixed speedup. Compare build times for your own dependency set with and without cache reuse, and inspect the build logs when installation unexpectedly slows down.

Copy link to headingPython versions pinned with .python-version

uv.lock can cover multiple Python versions, but deployments still need an interpreter compatible with the project's requires-python range and its dependencies.

Vercel supports Python 3.12, 3.13, and 3.14, with 3.12 as the default when no supported version is declared. Use uv python pin 3.12 to write that version to .python-version, and keep it compatible with requires-python in pyproject.toml. Vercel also accepts version information from Pipfile.lock.

Copy link to headingBundle limits sized for large dependency trees

Machine learning packages and native extensions can push a Python dependency set past a conventional function bundle long before application code adds much. Teams then end up splitting functions or stripping dependencies to fit.

Python Functions have a standard uncompressed bundle limit of 500 MB. The Large Functions beta supports up to 5 GB with Fluid compute and Active CPU enabled. Secure Compute and Static IPs are not supported during the beta.

Python bundles have no automatic tree-shaking. Use excludeFiles under the function's configuration in vercel.json to remove unnecessary tests, fixtures, and other files, and keep runtime dependencies limited to what the application uses.

Copy link to headinguv preinstalled in Vercel Sandbox

Vercel Sandbox's default managed universal image includes Python 3.14 and uv for installing dependencies within a session.

The image's rolling latest tag receives updates. Pin an image digest when the execution environment needs to remain reproducible.

Copy link to headingShip faster Python builds on Vercel

Start with one project's tested dependency set. Preserve its versions during migration, run the tests with uv, and compare installation time under the cache conditions used by CI.

Import the repository into Vercel or browse Python framework starters to deploy it.

Copy link to headingFrequently asked questions about the uv Python package manager

Copy link to headingIs uv stable enough for production use?

Yes. uv is used in production, and its versioning policy places breaking changes in minor releases. Pin the uv version used by CI, review release notes, and test upgrades before changing that pin.

Copy link to headingShould a project keep both uv.lock and requirements.txt?

Keep both when another installer needs requirements.txt, but generate that file from uv.lock with uv export. Commit the export if the deployment workflow requires it, and regenerate it whenever the lockfile changes. Avoid maintaining two independent sets of pins.

Copy link to headingHow does uv interact with Vercel's build cache?

Each successful build updates the cache for the next one, and a failed build leaves it untouched, so one broken deploy doesn't degrade later installs. To rule the cache out while debugging, redeploy without the existing build cache or set VERCEL_FORCE_NO_BUILD_CACHE to 1.

Ready to deploy?