Snap CD vs Pulumi Deployments

Pulumi and Terraform represent two different philosophies of infrastructure as code. Pulumi lets you define infrastructure in general-purpose languages — TypeScript, Python, Go, C# — with the full power of loops, conditionals, and type systems. Terraform uses HCL, a purpose-built declarative language. Both work. The question becomes: once your infrastructure is defined, how do you orchestrate deployments across multiple stacks at scale?

Pulumi Deployments is Pulumi's answer — a managed orchestration layer built into Pulumi Cloud. Snap CD is a deployment orchestrator for Terraform and OpenTofu (with Pulumi support in preview). This guide compares the two approaches to help you decide which fits your team.

The language question

This is the most visible difference, but it's worth addressing upfront because it shapes everything else.

Pulumi programs are real code. You can unit test them, share logic via packages, and use your language's ecosystem. A database module in TypeScript can share interfaces with the application that uses it. This is genuinely powerful for teams with strong software engineering practices.

Terraform uses HCL — a declarative language that's simpler but more constrained. You can't write a for loop that conditionally creates resources based on an API call. But the constraint is also the point: a Terraform plan is a complete, reviewable description of what will change.

Snap CD is agnostic. It orchestrates whatever IaC tool your Runners execute. Today that's Terraform and OpenTofu (with Pulumi in preview). Your choice of language doesn't change how Snap CD manages dependencies, approvals, or execution.

Architecture

Pulumi Deployments

Pulumi Deployments runs your Pulumi programs on Pulumi Cloud's infrastructure. You configure deployment settings per stack, and Pulumi Cloud handles execution, state management, and secrets.

This means:

  • Your code runs in Pulumi's environment. Pulumi programs can contain arbitrary code — API calls, file reads, network requests. That code runs on Pulumi Cloud's workers, which need access to your cloud providers and potentially your internal network.
  • Secrets are managed by Pulumi Cloud. Stack secrets are encrypted with keys managed by Pulumi Cloud (or your own KMS via the paid tiers). This is convenient but means secrets pass through their infrastructure.
  • Customer-Managed Agents are available (on the Business Critical tier) for teams that need execution inside their own network. A fully self-hosted Pulumi Cloud is also available on Business Critical, but requires a separate license and guided onboarding.

Snap CD

Snap CD separates orchestration from execution. The Server (snapcd.io or self-hosted) handles configuration, dependency tracking, scheduling, and logging. Runners — lightweight agents deployed in your infrastructure — handle the actual execution.

  • Code and credentials stay in your environment. Runners clone your repo and execute terraform plan / terraform apply (or pulumi preview / pulumi up) locally. Nothing is uploaded to snapcd.io. See Self-Hosted Terraform Runners with Credential Isolation for the full deployment model.
  • The Server is available for self-hosting under a source-available license. There's no separate "enterprise" tier.
  • Runners connect outbound via authenticated WebSocket. No inbound firewall rules needed.
  • Execution is non-invasive — Runners run standard Terraform commands in a shell session. Your code has no Snap CD-specific constructs. See Non-invasive Orchestration.

Cross-stack dependencies

This is where the orchestration models diverge most significantly.

Pulumi Deployments

Pulumi's StackReference reads outputs from another stack:

const network = new pulumi.StackReference("org/networking/prod");
const vpcId = network.getOutput("vpcId");

This is similar to Terraform's terraform_remote_state — it reads the other stack's state to extract outputs. The problems are also similar:

  • Cyclic dependencies have no resolution. If stack A needs an output from stack B and stack B needs an output from stack A, there's no way to express this. You have to restructure your stacks.
  • Missing references crash the preview. If the referenced stack doesn't exist yet (a fresh deployment), the StackReference fails. You can't catch this with try/catch — the preview fails before your error handling runs.
  • Aliases break across stacks. Resource aliases — used for refactoring without destroying and recreating resources — don't work across stack or project boundaries.
  • No automatic cascading. When the networking stack's outputs change, nothing automatically re-deploys the compute stack. You trigger it manually, via CI, or by configuring Pulumi Deployments triggers.

Snap CD

Snap CD makes cross-state dependencies explicit with snapcd_module_input_from_output:

resource "snapcd_module_input_from_output" "vpc_id" {
  module_id        = snapcd_module.compute.id
  input_kind       = "Param"
  name             = "vpc_id"
  output_module_id = snapcd_module.networking.id
  output_name      = "vpc_id"
}

The Server knows the full dependency graph. When networking's outputs change, compute automatically re-plans. There's no state file reading across Modules — Snap CD handles the data flow internally. First-time deployments work because the dependency graph determines execution order; upstream Modules apply before downstream Modules attempt to read their outputs. See Modular Deployments for a detailed walkthrough.

Secrets management

Pulumi Deployments

Pulumi has built-in secrets management — values marked as secret are encrypted in the state file. This is a genuine advantage over Terraform, which stores secrets in plaintext in state. However, Pulumi's secrets lack project-level scoping, and pluggable secret backends have been requested for years.

Snap CD

Snap CD provides scoped secrets at the Stack, Namespace, and Module level, with support for Azure Key Vault as a secret backend. Sensitive outputs flowing between Modules are encrypted in Snap CD's secret store — they're never written to disk in plaintext.

Deployment triggers and drift detection

Pulumi Deployments

Pulumi Deployments can trigger deployments from:

  • Git push — a commit to a configured branch triggers a deployment.
  • Click to Deploy — manual trigger from the Pulumi Cloud console.
  • REST API — programmatic triggers via the Pulumi Cloud API.
  • Drift detection — scheduled reconciliation runs that detect and optionally correct drift.

Cross-stack triggers require explicit configuration. If stack B should re-deploy when stack A's outputs change, you configure that relationship in Pulumi Cloud's deployment settings.

Snap CD

Snap CD monitors Git sources continuously and triggers plans when new commits land. Cross-Module cascading is automatic — when a Module's outputs change, all dependent Modules re-plan without additional configuration. See Event-driven Continuous Deployment for how this works in practice.

Drift detection is built in, with configurable check intervals per Module. Drift-triggered plans always route through the normal approval workflow. See Detecting and Managing Terraform Drift.

Organisation model

Pulumi Deployments

Pulumi's organisational model has been a source of friction. The relationship between stacks, projects, and state has led to confusion — particularly around how stack names, backends, and project namespacing interact. The design of self-managed state backends is tracked as an ongoing epic.

Snap CD

Snap CD uses a three-level hierarchy: Stacks contain Namespaces, which contain Modules. Permissions, secrets, and Runners can be scoped to any level:

resource "snapcd_stack" "prod" {
  name = "prod"
}

resource "snapcd_namespace" "platform" {
  name     = "platform"
  stack_id = snapcd_stack.prod.id
}

resource "snapcd_module" "networking" {
  name            = "networking"
  namespace_id    = snapcd_namespace.platform.id
  source_url      = "https://github.com/myorg/infra-networking.git"
  source_revision = "main"
  runner_id       = data.snapcd_runner.platform.id
}

Approval workflows

Pulumi Deployments

Pulumi Deployments has Review Stacks — ephemeral stacks that preview changes before they're applied to the target stack. Combined with Policy Packs (OPA/CrossGuard), this provides a review workflow for infrastructure changes.

Snap CD

Snap CD has built-in approval thresholds per Module. You set the number of required approvals, and anyone with the Approver role at the Module's scope (or above) can approve. Plans are visible in the dashboard for review before approval.

resource "snapcd_module" "production_network" {
  name                     = "networking"
  namespace_id             = snapcd_namespace.prod.id
  source_url               = "https://github.com/myorg/infra-networking.git"
  source_revision          = "main"
  runner_id                = data.snapcd_runner.prod.id
  apply_approval_threshold = 2
}

Access control

Pulumi Deployments

Pulumi Cloud uses team-based access control with stack-level permissions. Teams can have read, write, or admin access to stacks. More granular policies require Policy Packs.

Snap CD

Snap CD has hierarchical RBAC with roles (Owner, Contributor, Reader, Approver) assignable at any level — organisation, Stack, Namespace, Module, or Runner. A user can be Contributor on the test Stack but Reader on prod, without writing policy code. See A Permission System Built for Infrastructure.

Lock-in and self-hosting

Pulumi Deployments

Pulumi Deployments requires Pulumi Cloud. A self-hosted version of Pulumi Cloud (including Deployments) is available on the Business Critical tier, but it requires a guided proof of concept and a separate license. Your Pulumi programs themselves are portable (you can run pulumi up from the CLI), but the orchestration layer is tied to the Pulumi Cloud platform.

Snap CD

Snap CD's Terraform code has no Snap CD-specific constructs. Runners execute standard terraform plan and terraform apply. If you leave Snap CD, your Terraform code doesn't change — you just need another way to orchestrate it. The Server itself is available for self-hosting under a source-available license.

Pricing

Pulumi Deployments

Pulumi Cloud offers a free tier for individuals. Team and enterprise tiers are priced per resource under management, with Pulumi Deployments billed separately at $0.01 per deployment minute beyond included allotments.

Snap CD

Snap CD prices based on Modules managed, users, and Module jobs. There's no per-Runner cost. The pricing is consumption-based, not seat-based with feature gates. All core features are included in the free Community Edition.

Comparison table

Dimension Pulumi Deployments Snap CD
IaC language TypeScript, Python, Go, C#, Java, YAML Terraform/OpenTofu (HCL), Pulumi (preview)
Architecture Pulumi Cloud (SaaS or self-hosted on Business Critical) Orchestration Server + self-hosted Runners
Cross-stack dependencies StackReferences (read other stack's state) snapcd_module_input_from_output (server-managed)
Automatic cascading Configurable triggers Built-in on output change
Secrets Built-in encryption (Pulumi Cloud KMS or custom) Scoped secrets + external store integration
Deployment triggers Git push, API, manual, drift schedule Continuous source monitoring + automatic cascading
Drift detection Scheduled reconciliation Scheduled with approval routing
Organisation model Projects + stacks Stacks → Namespaces → Modules
Approval workflow Review Stacks + Policy Packs Built-in approval thresholds + RBAC
RBAC Team-based, stack-level Hierarchical, scoped to Stack/Namespace/Module/Runner
Self-hosting Full platform on Business Critical tier; agents on lower tiers Full stack available (source-available license)
Lock-in Orchestration tied to Pulumi Cloud Standard Terraform code, no vendor constructs
Pricing Per resource + deployment minutes Per Module

When to choose which

Pulumi Deployments is a good fit when:

  • Your team writes infrastructure in TypeScript, Python, Go, or C# and wants to keep that investment.
  • You're already using Pulumi Cloud for state management and secrets.
  • Review Stacks and Policy Packs meet your approval and policy needs.
  • You prefer a fully managed platform and don't need to self-host the control plane.

Snap CD is a good fit when:

  • You use Terraform or OpenTofu and want orchestration without changing your IaC tooling.
  • Cross-state dependency management with automatic cascading is a primary need.
  • You want full control over where execution happens — Runners in your environment with your credentials.
  • You need hierarchical RBAC scoped below the Stack level (Namespace, Module, Runner).
  • Self-hosting the entire stack is a requirement.

Both? If your organisation uses both Terraform and Pulumi (common during migrations or when different teams have different preferences), Snap CD's Pulumi preview support means you can orchestrate both from a single control plane — each Module runs whatever IaC tool its Runner is configured for.

See also

Snap CD

Intelligent GitOps for Infrastructure as Code. Automate, orchestrate, and scale your infrastructure deployments with confidence.


© 2026 Snap CD. All rights reserved.

An unhandled error has occurred. Reload 🗙