Skip to content

Instantly share code, notes, and snippets.

@donbr
Created September 28, 2025 18:35
Show Gist options
  • Save donbr/68ed3314ea52247910d722b4ddfed368 to your computer and use it in GitHub Desktop.
Save donbr/68ed3314ea52247910d722b4ddfed368 to your computer and use it in GitHub Desktop.
The Authoritative Playbook for `uv` in Production Teams

The Authoritative Playbook for uv in Production Teams

This guide is the complete, canonical workflow for managing Python project dependencies using uv. It provides a clear, two-mode approach, production-ready best practices, and drop-in templates to ensure reproducibility, security, and developer efficiency across teams.

Core Concept: The Two Modes of uv

uv operates in two distinct modes. Your team should choose one and use it consistently.

  1. Project Mode (Recommended): This is the modern, preferred approach. It's managed by commands like uv add, uv lock, and uv sync, using the cross-platform uv.lock file as the single source of truth for reproducibility.
  2. Requirements Mode (Compatibility): This mode mirrors the classic pip-tools workflow and is useful when you need a requirements.txt file for legacy tools or specific deployment platforms.

The uv Workflow Diagram

sequenceDiagram
    participant Dev as Developer
    participant Pyproject as pyproject.toml
    participant UV as uv (CLI)
    participant Venv as Virtual Environment

    box Project Mode (Recommended & Canonical)
        participant Lock as uv.lock
    end

    box Requirements Compatibility
        participant Reqs as requirements.txt
    end

    alt Project/Lockfile Workflow (Recommended)
        Dev->>UV: 1a. Run 'uv add "fastapi>=0.110"'
        Note left of UV: Atomic: Edits pyproject.toml & updates uv.lock
        UV->>Pyproject: Modify 'dependencies'
        UV->>Lock: Update lock file

        Dev->>UV: 1b. (Optional) Run 'uv lock --upgrade-package fastapi'
        Note left of UV: Targeted upgrade
        UV->>Pyproject: Read constraints
        UV->>Lock: Update lock file with upgraded package

        Dev->>UV: 2. Run 'uv sync'
        Note left of UV: Reads uv.lock by default
        UV->>Lock: Read pinned dependencies
        UV->>Venv: Install/update/remove packages

    else Requirements.txt Compatibility
        Dev->>Pyproject: 1. Manually edit dependencies
        Note right of Pyproject: Manual step required

        alt Generate from pyproject.toml
            Dev->>UV: 2a. Run 'uv pip compile pyproject.toml -o requirements.txt'
            Note left of UV: Compiles from high-level intent
            UV->>Pyproject: Read abstract dependencies
            UV->>Reqs: Generate/overwrite requirements.txt
        else Export from uv.lock (Preferred)
            Dev->>UV: 2b. Run 'uv export --format requirements-txt > requirements.txt'
            Note left of UV: Exports exact versions from lockfile truth
            UV->>Lock: Read pinned dependencies
            UV->>Reqs: Generate/overwrite requirements.txt
        end

        Dev->>UV: 3. Run 'uv pip sync requirements.txt'
        UV->>Reqs: Read pinned dependencies
        UV->>Venv: Install/update/remove packages
    end
Loading

## Production-Ready Best Practices

1. Atomic Dependency Management

Use uv add and uv remove for all dependency changes. These commands are atomic, ensuring pyproject.toml and uv.lock remain perfectly in sync.

uv add "fastapi>=0.110"
uv add --group test pytest
uv remove fastapi

2. Manage Dependency Groups with [dependency-groups]

Use the PEP 735 standard [dependency-groups] table in pyproject.toml to manage development and testing dependency sets.

# pyproject.toml
[project]
dependencies = ["fastapi>=0.110"]
requires-python = ">=3.11,<3.13"

[dependency-groups]
dev = ["ruff>=0.5"] # Synced by default
test = ["pytest>=8"]

3. CI/CD and Pre-Commit Guardrails

Enforce lock file consistency in your CI pipeline and locally.

  • CI Check: Add this to your CI script to fail builds if the lock file is stale.
    uv lock --check
  • Pre-Commit Hook: Add a hook to .pre-commit-config.yaml to run this check automatically.
    - repo: local
      hooks:
        - id: uv-lock-check
          name: Check uv.lock freshness
          entry: uv lock --check
          language: python
          types: [toml]
          files: ^pyproject\.toml$

4. requirements.txt for Compatibility

If needed, export requirements.txt from the authoritative uv.lock file.

uv export --format requirements-txt > requirements.txt

Policy Note: In this repository, uv.lock is the single source of truth. A requirements.txt file is a temporary artifact.


## FAQ: Project Mode vs. Requirements Mode

  • When should I use Project Mode (uv.lock)?
    • Almost always. This is the default, modern, and most robust method. Use it for all new projects, especially those that need to work across different operating systems (macOS, Linux, Windows) or require strict reproducibility.
  • When should I use Requirements Mode (requirements.txt)?
    • For compatibility. Use this mode only when a legacy tool or deployment platform (e.g., some PaaS buildpacks, older CI systems) does not understand pyproject.toml and explicitly requires a requirements.txt file to function.

## Troubleshooting Common Issues

  • "My project was installed, but I didn't want it to be."
    • Symptom: You see your own project in pip list.
    • Fix: This is the default "editable install" behavior. For production-like environments or Docker builds, use uv sync --no-editable.
  • "Dependencies resolved on my Mac but failed in Linux CI."
    • Symptom: uv sync fails with a resolution error in a different OS.
    • Fix: Ensure your pyproject.toml has a requires-python entry that matches all target environments (e.g., requires-python = ">=3.11,<3.13").
  • "Error: uv.lock is not in sync with pyproject.toml."
    • Symptom: The uv lock --check command fails in CI.
    • Fix: A collaborator likely edited pyproject.toml manually without running uv lock. To fix, run uv lock locally, commit the updated uv.lock file, and push again.

## uv Quick Reference Cheatsheet

Project/Lockfile Workflow (Recommended)

uv venv                       # Create virtual environment
uv add fastapi                # Add a dependency
uv add --group dev ruff       # Add a dev dependency
uv sync --group test          # Sync venv with default, dev, and test groups
uv sync --no-dev              # Sync venv with production dependencies only
uv lock --upgrade-package fastapi # Update a single package
uv lock --check               # Verify lockfile is up-to-date (for CI/pre-commit)
uv run pytest                 # Run a command in the venv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment