Library / SDK
pdm-project/pdm avatar
pdm-project/pdm

PDM review: a PEP 621 Python package manager that does not pick your build backend

A modern Python package and dependency manager supporting the latest PEP standards

8,667 stars496 forksPythonMIT

At a glance

What is it?
PDM stores project metadata in pyproject.toml, writes a pdm.lock, and can install Python interpreters itself. The interesting part is what it refuses to decide for you: the build backend.
Who is it for?
PDM fits library authors and application teams who want PEP 621 metadata, a lockfile and the freedom to pick any build backend, and who are willing to accept a smaller plugin and plugin-documentation surface than Poetry has. Skip it if you are happy with Poetry or Pipenv and do not need that backend freedom, and skip it if you want a single tool that owns the whole pipeline end to end.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What PDM solves for Python projects that ship code

PDM is a Python package and dependency manager. The README describes it as a next-generation package manager that supports the latest PEP standards, and it names two of them explicitly: PEP 517 for build backends and PEP 621 for project metadata. The repository topics list pep582 and pep621 alongside package-manager and packaging, which tells you where the project's attention sits.

The audience is narrower than "everyone who installs Python packages". PDM is aimed at people who both develop and package code. The README's own comparison makes this split: Pipenv is described as useful only for developing non-installable applications, because it does not handle packages related to packaging your code. If you write a Django site, that gap never bothers you. If you publish a library, it does.

There is a second audience: teams that dislike being locked into one build backend. The README states that unlike Poetry and Hatch, PDM is not limited to a specific build backend, and that users can choose any backend they prefer. That sentence is the clearest statement of the project's position. Everything else in PDM is negotiable through config; the backend choice is deliberately left to you.

How PDM stores metadata, resolves dependencies and locks them

The data flow starts at pyproject.toml. PDM reads project metadata from that standardized file, per the README, and the repository's own pyproject.toml shows the shape: a [project] table with name, authors, requires-python, license and a dependencies array, plus a [build-system] table. PDM's own build-system block requires pdm-backend and pdm-build-locked and sets build-backend to pdm.backend, but that is PDM's choice for itself, not a requirement it imposes on your project.

Dependency resolution runs through resolvelib, which appears in the dependency list of PDM's own pyproject.toml. Package fetching and metadata reading come from unearth, version and requirement handling from packaging and dep-logic, and interpreter discovery from findpython. The README highlights a "simple and fast dependency resolver, mainly for large binary distributions", which is a claim about the resolver's design target rather than a number you can check from the README alone.

The lockfile is the output you commit. Running pdm add writes pdm.lock, and the README points you at that file to see what is locked for each package. Environments are managed in either a project location or a centralized location, similar to Pipenv, according to the README's comparison section. There is also an opt-in centralized installation cache, which the README compares to pnpm's approach of saving disk space and boosting installation speed. That cache is opt-in, so a default install does not get it.

Two experimental switches change the model underneath. Setting python.use_venv to false enables PEP 582, installing packages into a local project folder instead of a venv, which the README compares to how npm installs into node_modules. Setting use_uv to true routes installation through uv, and the README notes that uv does not work with PEP 582. Those two flags cannot both be on.

Installing PDM and adding your first dependencies

PDM requires Python 3.10 or higher, according to the README, and the project's own pyproject.toml sets requires-python to ">=3.10". The recommended path is the standalone binary installer script. On Linux or Mac, the README gives this command:

bash
curl -sSL https://pdm-project.org/install.sh | bash

On Windows, the README gives the PowerShell equivalent:

powershell
powershell -ExecutionPolicy ByPass -c "irm https://pdm-project.org/install.ps1 | iex"

The README also says you can download the standalone binary from the release assets, and it points to the installation section of the documentation for alternative methods such as a Python script or package managers. The repository root contains install-pdm.sh, install-pdm.ps1 and install-pdm.py, plus an install-pdm.py.sha256 checksum file, so the scripts are versioned in the repository rather than fetched from an opaque endpoint only.

Once PDM is on your PATH, the quickstart is two commands. First, create a project:

bash
pdm new my-project

The README says you answer prompts and end up with a PDM project containing a pyproject.toml ready to use. Then add dependencies:

bash
pdm add requests flask

The README notes you can add multiple dependencies in one command, and that after a while you should check pdm.lock to see what is locked for each package. That file, not pyproject.toml, is the record of resolved versions.

If you want to try the experimental uv path, the README gives the config command:

bash
pdm config use_uv true

And the PEP 582 switch, which the README marks as experimental:

bash
pdm config python.use_venv False

Remember the README's warning that uv does not work with PEP 582, so pick one.

Where PDM gets awkward: plugins, lockfile churn and the uv overlap

The plugin system is listed as a highlight, and the README says users can add functionality through plugins that can be shared by uploading them as distributions. That is a real extension surface, but the README itself does not document a plugin API, a hook list or a versioning policy for plugins. A curated index exists at Awesome PDM, which the README links, and that link is doing a lot of work: it is the practical answer to "does a plugin exist for X", and it is a community list, not a compatibility guarantee.

The lockfile is only as good as your discipline with it. PDM writes pdm.lock, and the README tells you to inspect it, but nothing in the README describes a rollback path if a resolution turns out to be wrong after you have committed it. You would be relying on version control, which is fine, but it means the tool does not offer you a safety net beyond git.

The uv integration deserves a direct judgement. The README says uv is a very fast Python package installer written in Rust and that PDM can use it via use_uv. If your main reason for considering PDM is installation speed, you are partly adopting a second tool to get it, and the two experimental modes conflict. The project's own framing of uv as an integration rather than a replacement is honest, but it also means PDM's performance story is partly someone else's story.

Finally, the centralized installation cache is opt-in. Teams that expect deduplication out of the box will be disappointed until they turn it on, and the README does not spell out the disk-layout consequences of enabling it.

PDM compared with Poetry, Pipenv and Hatch

The README does the comparison work, and the distinctions are concrete.

Pipenv combines pip and venv, and installs from Pipfile.lock or Pipfile. It does not handle packaging your code, so it suits non-installable applications. If you never build a wheel, Pipenv covers your case and PDM's packaging features are dead weight.

Poetry manages environments and dependencies similarly to Pipenv, and it can build .whl files and upload wheels and source distributions to PyPI. It has a plugin system and uses pyproject.toml. The README's own differentiator against Poetry is the build backend: Poetry is tied to its own, PDM is not. If you are happy with Poetry's backend, that difference is worth nothing to you.

Hatch manages environments and allows multiple environments per project, with a central location by default that can be reconfigured to the project root. It can package a project using PEP 621 compliant pyproject.toml files and upload to PyPI, but the README states it manages packages without lockfile support. That is the sharpest contrast in the whole comparison: if you need a lockfile, Hatch is out and PDM is in.

PDM's own summary of itself is that it manages venvs in both project and centralized locations, reads metadata from pyproject.toml, supports lockfiles, and allows plugins shared as distributions. Read against the three alternatives, the lockfile plus backend freedom combination is the actual pitch.

Maintenance, licensing and what an upgrade costs you

The repository is not archived. Its last push was on 2026-09-20, and the most recent release listed is 2.29.2 on 2026-09-17, following 2.29.1 on 2026-09-14 and 2.29.0 on 2026-08-29. Releases arrive frequently, and a CHANGELOG.md plus a news/ directory sit at the repository root, which is where a project records changes between releases. The project also carries a SECURITY.md and a CONTRIBUTING.md.

The licence is MIT, declared in pyproject.toml as license = "MIT" with license-files = ["LICENSE"], and the repository has a LICENSE file at the root. MIT is permissive and is compatible with commercial use, but this is a factual description of the licence identifier, not legal advice; if your organisation has licence review rules, run the MIT text past whoever owns that process.

Upgrade cost is where the experimental flags matter. python.use_venv and use_uv are documented as experimental, and the README states they are mutually exclusive. Code or CI that depends on either behaviour is depending on a setting the project has labelled experimental, which is the kind of thing that can move between minor releases. The frequent release cadence (three releases in the three weeks before the last push) means pinning PDM in CI is a reasonable habit, and the standalone installer scripts in the repository root give you a way to install a specific version rather than tracking latest.

PDM's own dependency list is long, including httpx, hishel, truststore, virtualenv, resolvelib and pbs-installer. That is not a problem, but it does mean PDM's own install footprint is not trivial, and a security review of your supply chain will end up reading that list.

Editorial conclusion

PDM fits library authors and application teams who want PEP 621 metadata, a lockfile and the freedom to pick any build backend, and who are willing to accept a smaller plugin and plugin-documentation surface than Poetry has. Skip it if you are happy with Poetry or Pipenv and do not need that backend freedom, and skip it if you want a single tool that owns the whole pipeline end to end. Before adopting, verify the exact interpreter requirement for your CI images, check that the plugins you depend on exist in the Awesome PDM list, and decide whether you want the default venv layout or PEP 582. The first command to run in a scratch directory is pdm new, because the generated pyproject.toml is the whole contract this tool works from.

Frequently asked questions

What does PDM require to run?

The README states PDM requires Python version 3.10 or higher, and the project's own pyproject.toml sets requires-python to ">=3.10". You can alternatively download the standalone binary from the release assets.

How do I install PDM on Linux or macOS?

The README recommends the standalone binary installer script: curl -sSL https://pdm-project.org/install.sh | bash. It also points to the documentation's installation section for alternative methods such as a Python script or package managers.

How do I create a new PDM project and add dependencies?

The README's quickstart uses pdm new my-project, where you answer prompts and get a project with a pyproject.toml. Then pdm add requests flask adds dependencies, and you can check pdm.lock to see what is locked for each package.

Can PDM use uv as the installer?

Yes, the README documents pdm config use_uv true to enable uv integration, describing uv as a very fast Python package installer written in Rust. The README also warns that uv does not work with PEP 582.

Does PDM lock dependencies like Poetry does?

The README states PDM reads project metadata from pyproject.toml and supports lockfiles, and the quickstart tells you to inspect pdm.lock after adding packages. The README contrasts this with Hatch, which it describes as managing packages without lockfile support.

Official sources

  1. License: MIT
  2. pdm-project/pdm on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pdm-project-pdm.svg)](https://hysenlabs.com/projects/pdm-project-pdm)