Packages and Dependencies
A package is a unit of code you install rather than write. You already depend on this idea: a Terraform provider comes from a registry, and a Pulumi YAML program declares the providers it needs in its project file. In a general-purpose language, that dependency is managed by the language’s own package manager, which resolves versions, downloads code, and records exactly what your program depends on.
The package manager per language
Every Pulumi language uses that language’s standard tooling; there’s no Pulumi-specific package format to learn.
- TypeScript and JavaScript: npm or Yarn, with dependencies declared in
package.json. - Python: pip, uv, or Poetry, with dependencies declared in
requirements.txtorpyproject.toml. - Go: Go modules, with dependencies declared in
go.mod. - C#: NuGet, with dependencies declared in the project’s
.csprojfile. - Java: Maven, with dependencies declared in
pom.xml.
Importing a package into your program uses that language’s own import syntax:
import * as aws from "@pulumi/aws" in TypeScript, import pulumi_aws as aws
in Python, and so on. There’s nothing to configure beyond what you’d already
do for any other dependency.
Providers are packages too
A cloud provider, such as AWS, Azure, or Google Cloud, is distributed as an
ordinary package in your language’s package registry, paired with a plugin
binary that Pulumi downloads and runs. When you scaffold a new project with
pulumi new, the template’s package file already lists the providers it
uses, and pulumi install resolves and downloads everything, dependencies
and plugins alike. You rarely have to think about the plugin layer directly;
it’s there so the same provider works consistently across every supported
language.
What to watch out for
Pin your versions and commit your lockfile, the same discipline you already
apply to Terraform provider version constraints. It matters more here than in
application code, because an unpinned provider upgrade can change a
resource’s default behavior between one pulumi up and the next, not just
its API surface. Treat a provider or package upgrade as a deliberate,
reviewed change.
The Pulumi Registry is where providers and Pulumi packages, including components other teams have published, are discovered and documented for every supported language. For components that are specific to your organization and shouldn’t be public, Pulumi Cloud supports private packages, so you get the same install-and-import experience internally without publishing anything externally.
Frequently asked questions
Do I still need to run pulumi plugin install?
Usually not. The Pulumi CLI installs any missing provider plugins automatically the first time you run pulumi preview or pulumi up in a project. Manual installation is for cases like pre-fetching plugins in CI, working offline, or pinning a specific plugin version ahead of time; it isn’t a step you need in ordinary day-to-day development.
How do I add a Pulumi provider to my project?
Through your language’s own package manager: npm install @pulumi/aws in TypeScript, pip install pulumi-aws in Python, a Go module dependency, Pulumi.Aws through NuGet, or com.pulumi.aws through Maven. You can also run pulumi package add to generate a local SDK directly from a plugin or schema, which is the same mechanism source-based component packages use.
How do I share a component privately with my organization?
Publish it to the Pulumi Private Registry with pulumi package publish against a tagged Git repository. Teammates can then discover the package in the registry and generate an SDK for it in whichever language they’re using, the same way they would consume any first-party provider.
Next steps
Revisit the series overview or apply what you’ve learned by organizing your projects and stacks.
Learn more
- Building and publishing packages for authoring a Pulumi package that other teams and languages can consume.