Package registries differ in dozens of ways, but most of those differences cluster into a few structural categories. Looking at them through the lens of design tradeoffs helps explain why they ended up where they did. The ecosyste.ms documentation repositories contain detailed data on over 70 registries; here I’m trying to draw out the shapes.

The categories below are roughly orthogonal dimensions. No registry is “just” one thing; each is a particular combination of choices. npmjs.com is database-backed, unreviewed, has flat-plus-scoped names, ships mostly source, and is run by a for-profit company. Debian’s repositories are filesystem-based, curated by maintainers, use distro-managed names, ship binaries, and are run by a foundation. Those combinations matter more than any single axis.

A companion post covers package manager clients: resolution algorithms, lockfiles, build hooks, and manifest formats. The data is also available as CSV. There are gaps; contributions welcome.

Contents: Architecture · Review model · Namespacing · Distribution model · Governance · Ecosystem scope · Version retention · Size · Mirroring

Registry architecture

How does the registry store and serve package metadata?

Database-backed web services are uploaded via API, with metadata in Postgres or similar. This model scales well and supports rich features like download counts and vulnerability reporting.

  • npmjs.com
  • pypi.org
  • rubygems.org
  • nuget.org
  • crates.io1
  • packagist.org
  • hex.pm
  • pub.dev
  • clojars.org
  • forge.puppet.com
  • anaconda.org
  • luarocks.org
  • community.chocolatey.org
  • open-vsx.org
  • galaxy.ansible.com
  • jsr.io

Git repositories as indexes use version control as the storage layer on the critical path. If you removed git, you’d need to replace it with a database. The git model provides history, is trivially mirrorable, and works offline once cloned. But it doesn’t scale indefinitely; Cargo had to add a sparse index to avoid downloading the entire registry on first use.

  • homebrew-core
  • cocoapods.org
  • vcpkg
  • conan.io
  • swiftpackageindex.com
  • Julia General registry
  • juliahub.com2
  • winget-pkgs
  • spack

Filesystem-based repositories serve generated index files statically from HTTP mirrors. The server does work only when the repository is updated, not when clients fetch. This is the pattern that the compact index brought to RubyGems.

  • apt/dpkg
  • yum/dnf
  • pacman
  • apk
  • zypper
  • Portage
  • cran.r-project.org
  • bioconductor.org
  • metacpan.org
  • hackage.haskell.org
  • pkgs.racket-lang.org3
  • FreeBSD ports
  • pkgsrc
  • Helm
  • postmarketOS
  • Adélie Linux

Source host as registry means no central registry. Packages are fetched directly from git hosts using URLs as identifiers.

  • Go modules
  • Deno
  • Carthage

Content-addressed stores identify packages by hash of inputs. Binary caches provide pre-built artifacts.

  • Nix
  • Guix

Reviewed / Unreviewed

Does someone look at packages before they’re available?

Unreviewed means anyone can publish immediately. You create an account, run a publish command, and your package is live within seconds. This enables growth but creates attack surface.

  • npmjs.com
  • pypi.org
  • crates.io
  • rubygems.org
  • packagist.org
  • nuget.org
  • hex.pm
  • pub.dev
  • clojars.org
  • juliahub.com
  • hackage.haskell.org
  • metacpan.org
  • forge.puppet.com
  • anaconda.org
  • luarocks.org
  • open-vsx.org
  • galaxy.ansible.com
  • jsr.io

Reviewed registries have maintainers review packages before they appear. These registries grow more slowly but catch problems earlier. In practice, “review” ranges from packaging QA and policy checks to security vetting; very few projects do systematic source code review.

  • Debian
  • Fedora
  • Ubuntu
  • homebrew-core
  • Alpine
  • Arch4
  • nixpkgs
  • F-Droid
  • cran.r-project.org
  • bioconductor.org
  • conda-forge
  • postmarketOS
  • Adélie Linux
  • spack
  • FreeBSD ports
  • pkgsrc
  • winget-pkgs
  • central.sonatype.com5

Moderated upload accepts uploads but has moderation layers or automated semantic checks.

  • package.elm-lang.org6
  • community.chocolatey.org7

Namespacing

How are packages named?

Flat namespaces give each package a single global name.

  • rubygems.org
  • pypi.org
  • crates.io
  • hex.pm
  • hackage.haskell.org
  • cran.r-project.org
  • juliahub.com
  • package.elm-lang.org
  • luarocks.org
  • community.chocolatey.org

Scoped namespaces add organizational prefixes like @babel/core or symfony/console.

  • npmjs.com
  • packagist.org
  • forge.puppet.com
  • open-vsx.org
  • galaxy.ansible.com
  • winget-pkgs
  • artifacthub.io
  • anaconda.org
  • jsr.io

Hierarchical namespaces use structured naming like org.apache.commons:commons-lang3 or DateTime::Format::Strptime.

  • central.sonatype.com
  • metacpan.org
  • clojars.org

URL-based identifiers like github.com/user/repo use domain ownership as the claim. No registration step.

  • proxy.golang.org
  • deno.land
  • Swift Package Manager
  • Carthage

Distro-managed names are controlled by distribution maintainers, often differing from upstream project names.

  • Debian
  • Fedora
  • Arch
  • Alpine
  • homebrew-core
  • nixpkgs
  • spack
  • conda-forge
  • FreeBSD ports
  • pkgsrc
  • postmarketOS

Distribution model

What gets distributed?

Source only ships code that gets compiled or interpreted on the client. One artifact supports any platform.

  • npmjs.com
  • crates.io
  • proxy.golang.org
  • metacpan.org
  • hex.pm
  • hackage.haskell.org
  • cran.r-project.org
  • package.elm-lang.org
  • pkgs.racket-lang.org
  • clojars.org8
  • luarocks.org
  • galaxy.ansible.com
  • artifacthub.io
  • jsr.io

Binary only ships precompiled artifacts.

  • central.sonatype.com
  • nuget.org
  • apt/dpkg
  • yum/dnf
  • pacman
  • apk
  • community.chocolatey.org
  • winget-pkgs

Mixed source and binary provides source distributions plus prebuilt wheels/binaries. Native code gets platform-specific builds.

  • pypi.org
  • rubygems.org
  • cocoapods.org
  • anaconda.org
  • homebrew-core9
  • cache.nixos.org10
  • spack11
  • FreeBSD ports
  • pkgsrc

Platform matrices publish multiple artifacts per release: cp39-manylinux_x86_64, cp310-macosx_arm64, etc.

  • pypi.org
  • rubygems.org
  • anaconda.org
  • cache.nixos.org
  • nuget.org12
  • homebrew-core

Registry governance

Who runs the registry?

Non-profit foundations operate registries as community infrastructure.

  • pypi.org13
  • crates.io14
  • rubygems.org15
  • central.sonatype.com16
  • packagist.org17
  • metacpan.org18
  • hex.pm19
  • clojars.org20
  • hackage.haskell.org21
  • cran.r-project.org22
  • homebrew-core23
  • open-vsx.org24
  • artifacthub.io25

For-profit companies run registries as products or strategic infrastructure.

  • npmjs.com26
  • nuget.org27
  • pub.dev28
  • anaconda.org29
  • juliahub.com30
  • forge.puppet.com31
  • galaxy.ansible.com32
  • community.chocolatey.org33
  • winget-pkgs34
  • proxy.golang.org35
  • deno.land36
  • jsr.io36

Community projects run registries as volunteer efforts, often with fiscal sponsors.

  • cocoapods.org
  • conda-forge
  • swiftpackageindex.com
  • luarocks.org
  • Carthage
  • nixpkgs

Distribution projects maintain repositories as part of their distro.

  • Debian
  • Fedora37
  • Ubuntu38
  • Arch
  • Alpine
  • postmarketOS
  • Adélie Linux
  • spack
  • FreeBSD
  • pkgsrc

Ecosystem scope

What kind of software does this package manager handle?

Language-specific registries serve a single programming language ecosystem.

  • npmjs.com
  • pypi.org
  • rubygems.org
  • crates.io
  • hex.pm
  • hackage.haskell.org
  • metacpan.org
  • clojars.org
  • pub.dev
  • cran.r-project.org
  • juliahub.com
  • package.elm-lang.org
  • pkgs.racket-lang.org
  • packagist.org
  • proxy.golang.org
  • central.sonatype.com
  • luarocks.org
  • jsr.io

System-level registries install operating system components and applications.

  • apt/dpkg
  • yum/dnf
  • pacman
  • apk
  • homebrew-core
  • nixpkgs
  • Guix
  • zypper
  • Portage
  • FreeBSD ports
  • pkgsrc
  • community.chocolatey.org
  • winget-pkgs

Domain-specific registries serve particular use cases or industries.

  • bioconductor.org
  • conda-forge
  • spack
  • ROS
  • forge.puppet.com
  • registry.terraform.io
  • galaxy.ansible.com
  • artifacthub.io
  • open-vsx.org

Version retention

Does the registry keep old versions available? What happens when a published version needs to be removed?

Keeps all versions indefinitely. You can install any historical version.

  • central.sonatype.com39
  • proxy.golang.org40

Yanking marks a version as unavailable for new installs but keeps it accessible for existing lockfiles.

  • crates.io
  • rubygems.org
  • hex.pm

Time-limited deletion allows removal within a window, then versions become permanent.

  • npmjs.com41
  • pypi.org42
  • nuget.org
  • packagist.org
  • clojars.org
  • hackage.haskell.org
  • metacpan.org
  • pub.dev

Latest only or limited retention. Old versions disappear when new ones are published.

  • homebrew-core43
  • apt/dpkg44
  • Arch45
  • Alpine46

Registry size

How many packages? Grouped by order of magnitude.

10⁶+ (millions)

  • npmjs.com
  • proxy.golang.org
  • pypi.org

10⁵ (hundreds of thousands)

  • central.sonatype.com
  • nuget.org
  • packagist.org
  • rubygems.org
  • crates.io
  • cocoapods.org
  • anaconda.org
  • nixpkgs
  • Arch AUR
  • Fedora
  • Debian
  • Ubuntu

10⁴ (tens of thousands)

  • pub.dev
  • clojars.org
  • hex.pm
  • hackage.haskell.org
  • cran.r-project.org
  • FreeBSD ports
  • Alpine

10³ (thousands)

  • homebrew-core
  • luarocks.org
  • package.elm-lang.org

Mirroring / Proxying

How hard is it to run your own registry or mirror?

Trivial means filesystem-based repos or source-host registries that need no special infrastructure.

  • apt/dpkg
  • yum/dnf
  • proxy.golang.org
  • metacpan.org
  • cran.r-project.org

Supported means official tooling or documented processes exist for running mirrors or private registries.

  • npmjs.com47
  • pypi.org48
  • central.sonatype.com49
  • nuget.org
  • rubygems.org
  • crates.io
  • packagist.org
  • hex.pm50
  • luarocks.org51
  • clojars.org52
  1. Cargo originally required cloning the full crates.io-index git repo; the sparse index now allows fetching only needed entries. 

  2. JuliaHub has a database-backed front end but the underlying Julia General registry is a git repository. 

  3. pkgs.racket-lang.org stores packages as files, generates a JSON index, and serves via S3. It polls git sources for updates but doesn’t use git as its storage layer. 

  4. The AUR (Arch User Repository) is unreviewed; official repos are curated. 

  5. Requires proving domain ownership via DNS or hosting a file at the domain. 

  6. Elm enforces semantic versioning by diffing package APIs and rejecting publishes that break compatibility without a major version bump. 

  7. Three-stage automated review (validator, verifier, VirusTotal scan) plus human moderation. 

  8. Publishes JVM bytecode in JAR files, but these are built from source during the publish process. 

  9. Bottles are prebuilt binaries for common macOS versions. 

  10. Binary substitutes from cache.nixos.org avoid rebuilding from source. 

  11. Spack supports binary caches but defaults to building from source. 

  12. Runtime Identifiers (RIDs) specify platform-specific assets. 

  13. Python Software Foundation 

  14. Rust Foundation 

  15. Ruby Central 

  16. Originally Sonatype, now Linux Foundation 

  17. Funded by Private Packagist 

  18. Perl Foundation 

  19. Six Colors AB, community-funded 

  20. Clojurists Together 

  21. Haskell.org 

  22. R Foundation 

  23. Fiscally sponsored by Open Source Collective 

  24. Eclipse Foundation 

  25. Cloud Native Computing Foundation 

  26. GitHub/Microsoft 

  27. Microsoft 

  28. Google 

  29. Anaconda Inc 

  30. Julia Computing 

  31. Perforce 

  32. Red Hat. 

  33. Chocolatey Software. 

  34. Microsoft. 

  35. Google. 

  36. Deno Company.  2

  37. Red Hat 

  38. Canonical 

  39. Maven Central does not allow deletion or modification of published artifacts. 

  40. Once cached by proxy.golang.org, modules remain available indefinitely. 

  41. 72-hour window for unpublishing, with exceptions for security issues. 

  42. Can delete files and releases; PEP 763 proposes limiting this to 72 hours. 

  43. Formulas point to the latest version; older versions require tapping homebrew-core history. 

  44. Each Debian/Ubuntu release has its own repository snapshot. 

  45. Rolling release model; only current versions are available. 

  46. Each Alpine release has its own repository. 

  47. Verdaccio is the most popular private npm registry. 

  48. devpi and Artifactory provide PyPI-compatible private registries. 

  49. Nexus and Artifactory are widely used for hosting private Maven repositories. 

  50. Official mirror documentation with geographic mirrors available. 

  51. Custom rock servers can be configured via rocks_servers in the config file. 

  52. Mirror documentation with instructions for running your own.