Untitled_Post

Monorepos and UV: A Perfect Match for Modern Python Development

# Monorepos and UV: A Perfect Match for Modern Python Development UV, a fast Rust-based Python package manager, offers ideal solutions for monorepo management. Monorepos house multiple projects in a single repository, providing benefits like simplified dependency management and unified processes. UV excels with features specifically designed for monorepos, including workspace support inspired by Cargo, unified environment management with shared virtual environments, flexible dependency handling, and multi-Python version management. Its exceptional speed (10-100x faster than traditional tools) significantly improves developer workflows and CI/CD pipelines. Recent updates have enhanced workspace operations and dependency resolution. For organizations looking to implement Python monorepos, UV provides the necessary tooling for efficient, cohesive development while maintaining flexibility across services.

What is a Monorepo?

A monorepo (monolithic repository) is a version-controlled code repository that holds multiple projects, libraries, and services in a single place. While these projects may be related, they’re often logically independent and can be developed by different teams.

Companies like Google, Microsoft, Facebook, and Twitter are known to use monorepos at massive scale. For example, Google’s monorepo is estimated to be over 80TB in size with tens of thousands of commits daily.

Key Benefits of Monorepos

  1. Visibility: Everyone can see everyone else’s code, fostering collaboration and cross-team contributions
  2. Simplified dependency management: Sharing libraries is trivial as everything is in one place
  3. Single source of truth: One version of dependencies means no version conflicts
  4. Atomic commits: Updating multiple packages or projects in a single commit
  5. Unified build and testing processes: Standardized CI/CD across projects
  6. Shared timeline: Breaking changes are exposed immediately, encouraging communication

However, monorepos aren’t without challenges. As they grow, you may encounter performance issues, larger data volumes, and difficulty managing ownership of files. Many companies that use monorepos successfully invest heavily in custom tooling to address these challenges.

Introducing UV: The Modern Python Package Manager

UV is an extremely fast Python package and project manager written in Rust by Astral, the creators of Ruff and ty. It’s designed to replace multiple tools in the Python ecosystem:

  • pip and pip-tools for dependency management
  • poetry and pipenv for project management
  • virtualenv for environment management
  • pyenv for Python version management
  • and more

UV is 10-100x faster than traditional tools, making it an excellent choice for managing large Python codebases, especially monorepos. Currently with over 78,000 stars on GitHub, UV has become an essential part of the modern Python toolchain.

Why UV Excels at Monorepo Management

1. Workspace Support

UV’s workspace feature is directly inspired by Cargo workspaces in Rust, making it perfect for monorepos. Here’s how a typical monorepo structure looks with UV:

monorepo/
├── pyproject.toml          # Root workspace config
├── uv.lock                 # Shared lock file
├── services/
│   ├── service-a/
│   │   ├── pyproject.toml  # Service A's dependencies
│   │   └── src/
│   └── service-b/
│       ├── pyproject.toml  # Service B's dependencies
│       └── src/
└── packages/
    └── shared-lib/
        ├── pyproject.toml  # Shared library's dependencies
        └── src/

The root pyproject.toml defines the workspace:

[tool.uv.workspace]
members = ["services/*", "packages/*"]
# Optional root-level metadata
[project]
name = "my-monorepo"
version = "0.1.0"
requires-python = ">=3.11"

Each service or package has its own complete project definition:

# services/service-a/pyproject.toml
[project]
name = "service-a"
version = "0.1.0"
dependencies = [
    "fastapi>=0.100.0",
    "shared-lib",  # References workspace member
]

2. Unified Environment Management

One of UV’s key advantages for monorepos is its smart environment management:

  • Shared Virtual Environment: All workspace members share a single virtual environment at the workspace root
  • Dependency Deduplication: Common dependencies are installed once, saving disk space
  • Path Dependencies: Packages within the workspace can depend on each other using simple path references
  • Unified Lock File: A single uv.lock file at the root tracks dependencies across all packages

3. Flexible Dependency Management

When working with multiple services in a monorepo, UV gives you options:

  1. Install everything: uv sync at the workspace root installs dependencies for all workspace members
  2. Package-specific installations: uv sync --package service-a only installs dependencies for a specific service
  3. Dependency groups: Use optional dependency groups to separate concerns
# Example of dependency groups
[project.optional-dependencies]
dev = ["pytest", "black"]
production = ["gunicorn", "uvicorn"]

This is particularly useful in CI/CD pipelines where you want to minimize container sizes by only including necessary dependencies.

4. Python Version Management

UV also excels at managing multiple Python versions, which is often necessary in monorepos with diverse service requirements:

# Install specific Python versions
uv python install 3.12 3.13 3.14
# Create environment with specific Python version
uv venv --python 3.12
# Pin Python version for a project
uv python pin 3.11

5. Blazing Fast Performance

UV’s Rust implementation makes it 10-100x faster than traditional Python tools, which becomes increasingly important as your monorepo grows. This speed advantage means:

  • Faster CI/CD pipelines
  • Quicker developer setup times
  • Reduced friction when switching between services
  • More efficient dependency resolution

Setting Up a Python Monorepo with UV

Let’s look at a practical example of how to set up a monorepo with UV:

  1. Initialize the workspace:
mkdir my-monorepo && cd my-monorepo
echo '[tool.uv.workspace]\nmembers = ["services/*", "packages/*"]' > pyproject.toml
mkdir -p services packages
  1. Create a shared library:
mkdir -p packages/shared-lib/src
cd packages/shared-lib
uv init
# Edit pyproject.toml to define the shared library
  1. Create services that use the shared library:
mkdir -p services/api/src
cd services/api
uv init
# Edit pyproject.toml to include the shared library as a dependency
  1. Install all dependencies:
# From monorepo root
uv sync
  1. Run a service:
uv run --package api python -m api.main

Advantages of UV for Production Deployments

In production environments, UV’s monorepo capabilities shine:

  1. Selective deployments: Only deploy what’s needed for each service
  2. Reproducible builds: The lock file ensures consistency
  3. Efficient caching: UV’s global cache reduces redundant downloads
  4. CI optimization: Install only the dependencies needed for a specific build or test

Here’s a sample CI workflow for a service in a monorepo:

steps:
  - name: Checkout code
    uses: actions/checkout@v3
  - name: Install UV
    run: curl -LsSf https://astral.sh/uv/install.sh | sh
  - name: Install dependencies for API service
    run: uv sync --package api
  - name: Run tests
    run: uv run --package api pytest
  - name: Build container
    run: docker build -f services/api/Dockerfile .

Conclusion

UV represents a significant step forward for Python monorepo management, addressing many of the pain points that traditionally made monorepos challenging in the Python ecosystem. Its workspace support, unified dependency management, and blazing speed make it an ideal tool for organizations looking to adopt or improve their monorepo strategy.

By combining the collaborative benefits of monorepos with UV’s modern package management capabilities, development teams can achieve a more efficient, cohesive workflow while maintaining the flexibility to work on independent services.

Whether you’re managing a small collection of related packages or a massive organizational monorepo, UV provides the tools needed to make Python development more productive and enjoyable.


Ready to try UV with your monorepo? Install it with a simple command:

curl -LsSf https://astral.sh/uv/install.sh | sh

Or if you prefer to use pip:

pip install uv

For more information, check out UV’s documentation.

🚀 Unlock Ads-Free Experience At $5/year

14 days free trial Cancel anytime

16 thoughts on “Monorepos and UV: A Perfect Match for Modern Python Development”

Leave a Comment

Your email address will not be published. Required fields are marked *