Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

Infrastructure as code

Pulumi Consulting: Infrastructure as Code in Real Programming Languages

Pulumi is an infrastructure as code platform that lets you define cloud resources in general-purpose languages such as TypeScript, Python, Go and C#. We help teams structure projects and stacks, manage state and secrets, test their code and run previews and updates from CI, and we say plainly when Terraform or CloudFormation is a better fit.

Key takeaways

  • Pulumi uses real programming languages, so loops, functions, packages and unit tests are available natively.
  • That power cuts both ways: unrestrained code can be harder to review than declarative configuration.
  • State lives in Pulumi Cloud or a self-managed backend, and the choice affects access control, cost and operations.
  • Component resources are the main tool for encapsulating team patterns.
  • It suits teams with strong software engineering habits; it is less suited to operators who prefer a small declarative surface.

What teams use Pulumi for

Platform engineering with reusable components

Opinionated building blocks written as typed classes that product teams consume through a package registry.

Cloud infrastructure alongside application code

Teams that already work in TypeScript or Python keep infrastructure in the same language and review process.

Dynamic and data-driven infrastructure

Generating many similar resources from configuration or an API response using ordinary loops and functions.

Kubernetes and cloud together

Provisioning a cluster and the resources deployed to it in a single program with typed outputs flowing between them.

Migrating from Terraform or CloudFormation

Importing existing resources and converting configuration, one stack at a time.

What Pulumi is and the idea behind it

Pulumi starts from a simple proposition: infrastructure is software, so write it in a software language. A Pulumi program in TypeScript, Python, Go, C# or Java declares resources as objects. When you run a preview, the engine builds a resource graph from your program, compares it with recorded state, and shows what would change. An update then applies it. The workflow will feel familiar to anyone who has used Terraform; the authoring experience is what differs.

The benefit is real for the right team. You get functions, classes, package managers, type checking, IDE completion and ordinary unit tests. A platform team can publish a typed component for “a production database” and application teams call it like any library.

We deliver Pulumi work as part of our wider infrastructure as code practice, applying the same discipline we use elsewhere: reviewed changes, small blast radius and a pipeline that does the applying.

A short example

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const config = new pulumi.Config();
const env = pulumi.getStack();

const logs = new aws.s3.BucketV2(`logs-${env}`, {
  forceDestroy: false,
  tags: { environment: env, managedBy: "pulumi" },
});

new aws.s3.BucketPublicAccessBlock(`logs-block-${env}`, {
  bucket: logs.id,
  blockPublicAcls: true,
  blockPublicPolicy: true,
  ignorePublicAcls: true,
  restrictPublicBuckets: true,
});

export const bucketName = logs.bucket;

The same shape in a loop over environments or tenants is where a general-purpose language starts to save effort, and also where reviewers must pay attention.

How we structure Pulumi in production

Projects and stacks

A project is a program; a stack is one instance of it with its own configuration and state, typically one per environment. We keep stacks small and split projects by lifecycle and ownership: networking, data, cluster, applications. Stack references or outputs pass values between them. As with any tool, a single oversized stack slows updates and increases risk.

Component resources

Components are Pulumi’s way of encapsulating a pattern. A good component takes a small typed input, creates several underlying resources and exposes a few outputs. We publish them as internal packages with versioning and changelogs, so consumers upgrade on purpose. Over-abstraction is the common mistake: a component that tries to cover every case becomes harder to read than the raw resources.

Naming deserves attention too. Pulumi derives physical resource names from logical names plus a random suffix by default, which avoids collisions but can surprise people searching the console. We set explicit names only where an external system depends on them, since fixed names make replacement operations harder.

Testing

Because it is code, you can test it. Unit tests with mocks run quickly and check logic such as tagging rules and naming. Integration tests deploy to a scratch environment and are slower and costlier, so we use them sparingly for important components. Tests do not replace a reviewed preview; they complement it.

State, secrets and access

State holds resource identifiers and encrypted secrets. Pulumi Cloud offers hosted state, access control and an audit trail. A self-managed backend in object storage avoids a third-party service but moves access control, locking behaviour and operations to you. We choose with you based on compliance needs and team capacity, and we explain the trade-off in plain terms.

Secrets are encrypted in config and state using a secrets provider, which can be Pulumi’s service or a cloud key management service. For wider secret handling, Pulumi ESC or your existing secrets manager keeps values out of repositories. Pipelines authenticate to clouds with short-lived federated credentials rather than stored keys, and separate preview from update permissions where the platform supports it.

Policy as code (Pulumi policy packs) lets you block non-compliant resources at preview time, such as public buckets or untagged resources.

Cost and capacity

The open source engine is free. Hosted features may carry pricing that depends on your plan and resource counts, which you should check against current terms before committing. We do not state prices. Beyond licensing, the main costs are engineering time and the discipline needed to keep programs readable. Update speed depends on resource count and provider rate limits, so smaller stacks help.

Day-2 operations

  • Upgrades. SDKs, providers and the CLI move independently. Pin versions, upgrade in lower environments and read provider changelogs.
  • Drift. Run refresh previews on a schedule to compare state with reality, and reconcile deliberately.
  • Stack hygiene. Remove unused stacks, protect critical resources with the protect option and review who has access.
  • Dependency management. Treat the language’s packages as part of your supply chain, with lock files and vulnerability scanning.

Common failure modes

  • Clever code. Dynamic constructs that obscure what will be created. Keep the preview readable.
  • Language sprawl. Three languages across teams makes shared components impossible.
  • Replace surprises. Renaming a logical resource can replace the physical one. Use aliases and read previews.
  • Unmanaged secrets. Config values committed in plain text or leaked through outputs.
  • State loss. A self-managed backend without versioning or backup.

When Pulumi is the wrong choice

If your team is mostly operators who prefer a compact declarative format, Terraform is usually easier to hire for and review. If you are AWS-only and want AWS to hold state, CloudFormation is simpler to operate. If you need many teams to contribute small changes with minimal training, a restrictive language is an advantage, not a limitation. And if your main task is server configuration, Ansible is the better layer.

Moving between tools is possible but never free, so it is worth deciding properly. Our infrastructure as code service and a short consultation can help you weigh it.

Official documentation: www.pulumi.com/docs

How we work with Pulumi

  1. 01

    Check the fit

    We look at team skills, current tooling and review practices to confirm that a general-purpose language will help rather than hinder.

  2. 02

    Choose language and backend

    We select one language per organisation where possible and decide between Pulumi Cloud and a self-managed state backend.

  3. 03

    Structure projects and stacks

    Projects are split by ownership and lifecycle, with stack configuration separating environments.

  4. 04

    Build components and tests

    Reusable component resources are written with typed inputs, unit tests and, where useful, integration tests.

  5. 05

    Wire previews into CI

    Pull requests run a preview and post the diff. Merges run the update with scoped, short-lived credentials.

  6. 06

    Secure and hand over

    Secrets providers, policy packs, access and runbooks are configured and documented.

Pulumi compared with the alternatives

We recommend the tool that fits your team, not the one we know best. Here is when each option makes sense.

OptionChoose it when
PulumiPulumi is an infrastructure as code platform that lets you define cloud resources in general-purpose languages such as TypeScript, Python, Go and C#.
TerraformChoose it for the largest provider and module ecosystem, a small declarative language and wide hiring familiarity.
AWS CloudFormationChoose it for AWS-only estates where you want AWS to hold state and you prefer a native service.
AWS CDKChoose it if you want programming languages but only for AWS, deploying through CloudFormation rather than a separate state system.
AnsibleChoose it for configuring servers and orchestrating tasks rather than describing a cloud resource graph.

Tools we use alongside Pulumi

Pulumi CloudPulumi ESCPulumi PolicyTerraformAWSAzureKubernetesGitHub ActionsGitLab CI/CDNode.jsPythonGo

Frequently asked questions

What is Pulumi and how is it different from Terraform?
Pulumi defines infrastructure in general-purpose languages such as TypeScript or Python, while Terraform uses its own declarative language, HCL. Both compute a desired state, show a preview and track state. Pulumi gives richer programming constructs; Terraform offers a smaller, more uniform surface and a bigger module ecosystem.
Where does Pulumi store state?
By default in Pulumi Cloud, a hosted service that also provides access control and history. You can instead self-manage state in an object store such as S3 or Azure Blob, or on local files for experiments. We help you choose based on compliance, access control and who will operate it.
Is Pulumi open source?
The Pulumi command-line tool and SDKs are open source under the Apache 2.0 licence. The hosted Pulumi Cloud service is a commercial product with a free tier. You can use the open source engine with a self-managed backend if you prefer not to use the hosted service.
Can Pulumi use Terraform providers?
Yes, in many cases. Pulumi can bridge Terraform providers, which widens coverage, although native providers for major clouds are typically preferred. Coverage and behaviour vary by provider, so we verify the specific resources you need rather than assuming parity.
How do you keep Pulumi code reviewable?
We agree conventions: limited abstraction depth, typed component inputs, no hidden side effects, and previews posted on every pull request. Reviewers read the preview diff as well as the code, since the diff shows what actually changes in the cloud.
Can we migrate from Terraform to Pulumi?
Yes. Pulumi can import existing resources and offers conversion tooling for HCL, which gives a starting point rather than a finished result. We migrate stack by stack, require a no-change preview before cutover, and keep the old state until the new one is proven.

Talk to an engineer about Pulumi

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-09.