Why keep Pulumi state inside your own network, and which option fits
If a residency, air-gap or lock-in requirement stops your Pulumi state and secrets from living in Pulumi's hosted service, you have two realistic paths: self-hosted Pulumi Cloud, which is offered only on the Enterprise edition, or a DIY backend on object storage or PostgreSQL. The choice turns on one question: who must run locking, history, audit and recovery once state leaves the vendor? Self-hosted Pulumi Cloud moves much of that work to the vendor's software, while a DIY backend leaves each of those duties with your team, though you keep full control of the storage layer.
The supplied research covers PostgreSQL and MinIO in depth. PostgreSQL offers a liberal license, documented high availability through hot standby and synchronous or asynchronous replication, and continuous archiving for point-in-time recovery, but it does not detect a primary failure or promote a standby on its own, so you must choose and operate failover tooling. MinIO's community server is AGPLv3 and its repository is archived, so you should confirm its current maintenance status and licensing position with your legal team before relying on it for state. For object storage, ask whether versioning and object lock are enabled on the state bucket, since these matter for recovery from a bad apply.
For self-hosted Pulumi Cloud, confirm with Pulumi what the Enterprise edition installs, which components run in your cluster, how the console, locking and audit log are handled, what database it needs, how upgrades are delivered, and what support covers in an air-gapped setup. Ask for these answers in writing before you compare costs, because the licensing and support terms drive the total cost of each path. Then pick the option whose recovery and audit duties your team can staff and evidence.
What the constraint requires from the state backend
A residency or air-gap rule turns Pulumi state into a regulated record that must stay inside your boundary, be protected at rest, be attributable to a person, and be recoverable. Each card below is a requirement you can test against a self-hosted Pulumi Cloud deployment or a DIY backend before you commit to either.
Storage location and data residency
Pulumi state is a JSON record of every resource a stack manages, including resource identifiers, dependencies and any secret values. Under a residency rule, every copy of that record must sit inside the approved network or region, including replicas, logs and CI caches. For a DIY backend, that means the object store or PostgreSQL cluster runs in your accounts or data center. For self-hosted Pulumi Cloud, confirm where its database, object storage and worker logs are written. Ask the vendor to document every component that holds state.
Encryption and secrets handling
Secrets in Pulumi state are encrypted with the stack's secrets provider, so the choice of provider decides who can decrypt them. Keep the key material inside the boundary. A cloud KMS in the same account, or a self-managed key service, meets this. A passphrase-based provider keeps keys out of cloud services but puts key custody on your team. Verify that the state store itself is encrypted at rest and that TLS protects traffic between the CLI, the CI runners and the backend.
Access control and audit trail
Residency reviews usually ask who changed which stack, when, and with which identity. A DIY backend has no built-in audit log, so you must add one at the storage or database layer and tie it to named accounts. PostgreSQL offers several authentication methods, including certificate and LDAP, that can bind database access to your identity provider. Make sure every write to state is attributable to a person or a CI identity, and that break-glass access is logged and reviewed.
Backup and point-in-time recovery
A partial failure during an update can leave state out of step with real infrastructure, so recovery means rolling state back to a known point. Object stores need versioning or replication, while PostgreSQL can keep a base backup plus archived write-ahead logs for point-in-time recovery. Test a restore into an isolated environment on a schedule, and confirm that backups stay inside the same residency boundary as the live state.
Offline patching and package verification
An isolated network cannot pull updates on its own, so every patch arrives on approved media and must be verified before install. NERC CIP-013-2, which applies to electric utilities, requires procurement processes that verify the integrity and authenticity of vendor software and patches. Outside that sector, the same idea applies: check checksums or signatures on every package carried across the boundary. The MinIO community edition now ships as source only, so plan to build and verify it yourself.
How self-hosted Pulumi Cloud and DIY backends meet the constraint
This table compares self-hosted Pulumi Cloud Enterprise with three DIY backends for Pulumi state inside your network: S3-compatible object storage (MinIO, Ceph RADOS Gateway, SeaweedFS or Garage) and PostgreSQL. Read each row across where state lives, who provides locking and history, and who supports the system. The main takeaway is that the DIY options leave locking, history and audit design to your team, while the Enterprise edition keeps them in the vendor's product once its coverage is confirmed in writing.
| Option | How state stays in your network | Locking, history, audit and access | Trade-offs and support |
|---|---|---|---|
| Self-hosted Pulumi Cloud Enterprise | Runs in your environment, so state and secrets are held inside your network under the vendor's deployment model. | Locking, history and access control come from the product. Confirm exactly which features the self-hosted edition includes. | Enterprise edition only. Confirm feature coverage, deployment footprint and support terms in writing with Pulumi. |
| DIY backend on MinIO | State files sit in a bucket on storage you operate, inside your network. | Versioning, bucket policies and logs are yours to configure. Locking must be designed around the bucket. | Community repositories are archived and the AGPLv3 server ships as source only. Vendor support is through AIStor. |
| DIY backend on Ceph RADOS Gateway, SeaweedFS or Garage | Same bucket model, on a storage cluster you run in your data center or cloud account. | Access policies, audit logs and any locking approach are your responsibility. Confirm each project's capabilities. | Requires operating a storage cluster. Support comes from project communities or a vendor you contract separately. |
| DIY backend on PostgreSQL | State is held in a database you control, with access limited by your network rules and chosen authentication methods. | Transactions give a consistent store. History relies on your backups and WAL archiving for point-in-time recovery. | PostgreSQL License. Version 17 is supported to November 8, 2029 and 18 to November 14, 2030. Failover needs external tools. |
How a DIY backend recovers from partial failures
A self-managed state store has to survive three failures: an interrupted write during a stack update, the loss of the primary PostgreSQL database, and a corrupted or deleted bucket. An interrupted write can leave a stack's state half-updated relative to the cloud resources it describes, so the recovery plan must start with reconciling state against live infrastructure, not just restoring a file. Whichever backend you choose, confirm how the Pulumi CLI behaves when a update is cut off mid-run, and whether a retry resumes cleanly or needs a manual pulumi refresh first. Written down, that answer is the runbook's first step.
For a PostgreSQL backend, a hot standby serves read-only queries and can be promoted if the primary fails. The choice between synchronous and asynchronous replication is a trade-off you must make explicitly: with synchronous replication a commit waits for the standby, so a primary failure loses no acknowledged state writes, but a slow or unreachable standby slows every update. Asynchronous replication keeps updates fast but can lose the most recent commits on failover. Note that PostgreSQL does not detect a failed primary or promote a standby on its own. Automatic failover needs an external tool, and that tool's fencing behavior must be tested, because a split-brain state store can accept conflicting updates to the same stack.
The backstop is continuous archiving with point-in-time recovery, which replays archived WAL onto a base backup so you can restore to a moment before a bad write or deletion. Object storage needs its own protection, such as versioning and retention settings, so that a deleted or overwritten state file can be recovered. Recovery drills, not configuration alone, prove this design: restore a backup into an isolated environment, run pulumi preview against it, and time the result. Ask Pulumi to confirm what recovery behavior the self-hosted Pulumi Cloud edition provides before you rely on it.
How to deploy the chosen backend inside the boundary
This sequence takes a team from the backend decision to a tested, documented deployment inside its own network, whether the choice is self-hosted Pulumi Cloud or a DIY object store or PostgreSQL backend. The output is a working state backend, a verified restore path and a written patch procedure.
Confirm edition and deployment requirements
Start by confirming with Pulumi which edition, license terms and deployment requirements apply to self-hosted Pulumi Cloud, since the self-managed option is limited to the Enterprise edition. Ask for the supported installation method, the required components, the resource and network requirements, and what Pulumi provides for air-gapped installs. If the team chooses a DIY backend instead, record the object store or PostgreSQL cluster, its replication topology and its owner. The step is done when the decision, the named owners and the open questions are written down and signed off by the platform and security leads.
Build the cluster from an internal registry
If the network is air-gapped, mirror every image, package and binary into an internal registry or offline repository before anything is installed. For Kubernetes-hosted components, the kubeadm documentation describes listing and pulling control plane images in advance and pointing kubeadm init at a private registry with the --image-repository flag. For PostgreSQL, the platform team stages the server packages and verifies them against the vendor's published checksums before they cross the boundary. The step is done when a clean build succeeds using only internal sources, and the list of artifacts with their hashes is stored in the change record.
Configure encryption and authentication
Enable TLS for every client connection and choose the authentication method for each access path. PostgreSQL documents password, GSSAPI, SSPI, LDAP, RADIUS, certificate, PAM and OAuth methods, and PostgreSQL 18 deprecates MD5 password authentication in favor of SCRAM, so SCRAM or certificates are the baseline for new clusters. Map directory groups to database roles and limit the administrator role to a small named group. For state files, decide whether to use client-side encryption with a key provider such as AWS KMS, GCP KMS or OpenBao, or rely on the storage layer. The step is done when a test login with each method succeeds and a login with a disallowed method is refused.
Wire the Pulumi CLI and secrets provider
Point the Pulumi CLI at the chosen backend using the backend URL for the self-managed service or the object store or PostgreSQL location for a DIY backend, and confirm that stack state is written where the team expects. Select a secrets provider that runs inside the network, such as a key service or passphrase-based encryption, and confirm that no secret material is sent to an external endpoint. Document how CI runners authenticate to the backend and where their credentials are stored. The step is done when a stack can be created, written to and read back from the backend by a named runner, and the network path is confirmed by a check from outside the boundary that fails as expected.
Run a test stack and a restore drill
Deploy a small non-production stack through preview, update and destroy, and confirm that the lock, history and stack export behave as the team expects. Then run a restore drill: back up the backend, restore it to a separate environment, and run a preview against the restored state. For PostgreSQL, the continuous archiving and point-in-time recovery documentation describes the archive and base backup components that such a drill should exercise. For object storage, test versioning or replication and confirm that a deleted state object can be recovered. The step is done when the restored state produces the same preview output and the drill's timing and steps are recorded.
Document upgrade and patch procedures
Write the procedure for minor updates, major upgrades and emergency patches, and assign an owner for each. PostgreSQL minor releases do not change the storage format, so an update replaces executables and restarts the server, while major upgrades use dump and restore, pg_upgrade or logical replication. Record which versions are supported and when each one reaches end of life, using the PostgreSQL versioning policy as the reference. Describe how new images, packages and signatures are verified, scanned and imported through the same internal registry, and how this matches the software integrity controls in your NERC CIP-013-2 supply chain procedure if that standard applies. The step is done when a patch has been carried through the procedure once on the test environment and the evidence is filed.
Choosing self-hosted Pulumi Cloud or a DIY backend by situation
Choose this path when drift detection, policy checks and team permissions are part of how your organization runs infrastructure, and when Enterprise licensing fits your procurement process. The self-hosted edition keeps state inside your network while the vendor supplies features that a DIY backend would require your team to build and maintain.
- What you gain: Scheduled drift detection, policy enforcement and team-level permissions delivered as product features instead of CI jobs your team maintains.
- What you must build: Hosting, upgrades, backups and monitoring for the self-hosted service, plus integration with your identity provider.
- What recurs: The Enterprise license. Ask what it covers, how resources or users are counted, and what renewal terms apply.
- Who supports it: Confirm the support tier, response commitments and whether the vendor covers the upgrade path for the self-hosted edition.
- Exit path: Confirm that you can export stacks and state if you later leave, since migration depends on it.
Before deciding, compare the feature list of the self-hosted Enterprise edition with the features your team uses today, because hosted features are not guaranteed to appear in the self-hosted build.
Choose this path when platform engineers can operate a small set of stateful services and want the state store simple enough to review end to end. A DIY backend on S3-compatible object storage or PostgreSQL removes the license dependency for the state layer, but the locking, history, access control and audit trail that a hosted service provides become your responsibility.
- What you gain: No license fee for the state layer, and a store small enough to review, with access recorded by the storage or database layer you already operate.
- Recovery from failure: PostgreSQL supports continuous archiving and point-in-time recovery, along with hot standbys using synchronous or asynchronous replication. It does not detect a failed primary on its own, so you need an external failover tool.
- What you must build: Concurrency control for simultaneous updates, state versioning and retention, a secrets provider, and drift checks run from CI.
- Audit: Build an audit trail from storage access logs or database audit logging, and define who may read state that contains sensitive values.
- Support: Support comes from your own team and the upstream communities you rely on, so plan on-call coverage and patch timing in advance.
Before deciding, confirm how your chosen backend handles locking, and confirm that your PostgreSQL major version is within its support window. PostgreSQL's upgrading guidance describes the options for major version changes.
Choose this path when the network has no route to the internet and every CLI, provider, container image and package must cross a controlled boundary. In this situation the build and patch path matters more than the feature list, because a state backend that cannot be updated safely becomes a liability.
- Offline artifacts: Mirror the Pulumi CLI, provider plugins, language packages and container images into the enclave, and record their hashes at import.
- Cluster images: Pull control plane images ahead of time with kubeadm and point kubeadm init at a private registry. If you use MinIO for S3-compatible storage, note that its community repositories are archived and distributed as source only, so your team owns the build pipeline.
- Integrity checks: Verify the integrity and authenticity of every package and patch at each boundary crossing. NERC CIP-013-2 describes this kind of supply chain control for vendor software in the electric sector.
- Patch cadence: Plan how security fixes for PostgreSQL minor releases and storage components reach the enclave, since minor releases replace executables and require a restart.
- Vendor edition: Confirm whether the self-hosted Enterprise edition supports offline installation and license activation without outbound calls.
Before deciding, confirm with the vendor and your accreditor which mirror, licensing and upgrade procedures are supported in an isolated network.
Evidence auditors and regulators ask for from the state backend
Whether the state lives in Self-hosted Pulumi Cloud or a DIY backend on object storage or PostgreSQL, the reviewer asks the same questions: where the state is, who touched it, whether it can be restored, how the database or store is configured, and how software entered the network. The items below are the records that answer those questions. DeployOpen prepares this evidence, but independent auditors and certification bodies issue any audit report or certification.
Inventory of state and secret locations
List every backend, bucket, database and secrets provider that holds Pulumi state or stack configuration, with its host, region, owning team and encryption setting. Include exports, CI caches and local developer copies, since those are where state often leaks outside the designated store. For Self-hosted Pulumi Cloud, confirm with the vendor which components store state and which store secrets. Reconcile the inventory against the network diagram at each review.
Access logs and role assignments
Keep a current record of who can read, write and administer state, with the role each person holds and the date it was granted. Pull access logs from the object store or database and from the Pulumi service, and check that they capture reads of state files, not only writes. Remove stale service accounts and CI credentials on a schedule. A DIY backend relies on the storage platform's logs, so confirm retention with the team that runs it.
Backup and restore test records
Auditors look for proof that a backup was restored, not only that a backup job ran. Record the restore date, the source backup, the target environment, who performed the test and whether the stacks reconciled afterward. For PostgreSQL, continuous archiving and point-in-time recovery are the documented methods, so test both. Partial failures matter most here: a state file restored from an older point can make the next plan propose destructive changes.
Configuration baselines for the store
Document the hardening baseline for the PostgreSQL server or object store: TLS settings, authentication methods, versions in use, replication mode and patch level. For PostgreSQL, record the authentication method and confirm that MD5 password authentication is disabled in favor of SCRAM. Keep the baseline under version control and capture the diff at each change. Confirm the supported version window for the release you run before the review.
Package and image verification records
Where the network is isolated, every package, container image and IaC provider carried across the boundary needs a record of its source, checksum or signature check, and the person who approved it. This is the evidence behind the supply chain controls in NERC CIP-013-2 for utilities, and similar expectations apply elsewhere. Keep the transfer manifest, the approval ticket and the verification output together. Ask whether your own sector regulator expects this for IaC providers as well.
Questions teams ask before choosing a self-hosted Pulumi backend
What drives the cost of self-hosted Pulumi Cloud compared with a DIY backend?
Self-hosted Pulumi Cloud is licensed through the Enterprise edition, so the largest line item is the subscription, which you must price with Pulumi. A DIY backend has no license fee, but it moves cost to storage, a database host or managed PostgreSQL, backup targets, a secrets provider, CI runner time and the engineering hours to rebuild locking, history, audit trails and access control. Ask Pulumi for the Enterprise terms in writing, including what is one-time and what recurs. For the DIY side, list each component and who pays for it, then estimate operations time with your own staff. Storage and runner costs scale with stack count and run frequency, and engineering effort scales with how many hosted features your teams rely on today.
How long does it take to move Pulumi state inside our network?
The duration depends on the number of stacks, how much state history you keep, how many CI pipelines call Pulumi, and whether network paths, identity and backups are already in place. Self-hosted Pulumi Cloud adds an installation and integration phase, while a DIY backend adds design, build and testing of the storage, database, locking and access layers. Neither figure is supplied here, so ask Pulumi and any implementation partner for a timeline tied to a written scope. Plan the cutover as a separate phase with a rollback path, and confirm which stacks can move first.
What must our team provide before a self-hosted Pulumi backend can run?
Before any install or build starts, you need network access from CI runners and engineer workstations to the backend, a decision on how users authenticate, and somewhere durable to send backups. For self-hosted Pulumi Cloud, confirm the hosting target, certificates, DNS and the identity provider that will issue logins. For a DIY backend, you also need an object storage bucket or PostgreSQL instance with versioning or point-in-time recovery, and a secrets provider for stack configuration. Name an on-call owner for the backend, a patch owner and a person who approves restores. Without these owners, the platform works until the first incident and then stalls.
Can our team run a DIY Pulumi backend alone, and where does outside help matter?),
A team with platform engineers who already run PostgreSQL or object storage can usually build and operate a DIY backend without outside help, but the hard parts are recovery and access control. PostgreSQL does not include automatic failover, so you need external tools and a tested procedure for promoting a standby. Point-in-time recovery requires continuous archiving that someone must monitor. Outside help usually matters for the design review, the restore drill, the audit trail design and the handover runbook. Under a fixed-scope engagement, DeployOpen can plan, implement, harden, back up and document a self-hosted platform in your own cloud account or data center, and offer retainers for upgrades and continuous support.
How should we read a quote for a self-hosted Pulumi setup?
A useful quote separates each component: the Pulumi Enterprise subscription or the DIY infrastructure, the implementation work, the migration of stacks, the backup and restore testing, and the handover documentation. Ask for the scope, deliverables, assumptions and exclusions in writing before work begins, because most disagreements come from unstated assumptions such as how many stacks move or who supplies the identity provider. Ask which items recur, including license renewal, storage growth, database upgrades and support retainers. DeployOpen issues quotes from a written scope and does not publish a price list, so ask for the scope first.
What support does each option include, and what should we confirm in writing?
Self-hosted Pulumi Cloud support depends on the Enterprise agreement, so ask Pulumi which response times, severity levels, upgrade assistance and hours it covers. A DIY backend has no vendor support contract, which means support comes from your own staff, from the open-source projects you run, or from a retainer with an implementation partner. Confirm with Pulumi whether self-hosted Pulumi Cloud can be upgraded on your schedule and what is needed to restore it. For DIY, write down who answers a PostgreSQL or object storage incident, which upstream channels you rely on, and what outside retainer covers. Do not treat any support term as settled until it appears in a signed document.
How do PostgreSQL support windows affect a DIY Pulumi backend?
PostgreSQL supports each major version for a fixed window, so the version you choose sets your upgrade schedule. Version 18 was first released on September 25, 2025, and its final release is November 14, 2030. Version 14 is supported until November 12, 2026, so a backend built on it needs a planned major upgrade before then. Minor releases come at least every three months and do not change the storage format, so they are a routine restart. Major upgrades use dump and restore, pg_upgrade or logical replication, which can limit downtime to several seconds. Confirm the upgrade method and test restores before each upgrade.
How DeployOpen implements a self-hosted state backend
DeployOpen plans, implements, hardens, backs up and documents self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For a Pulumi state backend, that means agreeing in writing where state, secrets and audit records will live, how they are protected and recovered, and who operates them after handover.
How we scope
- We confirm which Pulumi edition, if any, your organization can run, and whether a self-hosted Pulumi Cloud or a DIY backend fits your requirements.
- The written scope lists the state storage, database, secrets provider, locking, access control and audit sources included in the engagement.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts, and a quote follows from that scope.
How we build
- We deploy the chosen state backend in your environment and configure encryption, backups and access paths against your own security baseline.
- We test partial-failure recovery, including interrupted applies, restored state copies and failover of the database that holds stack metadata.
- We document the stack migration steps, rollback path and evidence needed for internal reviews and external compliance assessments.
How we hand over
- We hand over runbooks for backup restore, state recovery, secret rotation and upgrades, written for your platform and operations teams.
- Your team receives a record of configuration, access decisions and test results so reviewers can trace how the backend was set up.
- DeployOpen prepares systems, controls and evidence for assessments; independent auditors and certification bodies issue any audit reports.
How we support
- Ongoing support, upgrades and continuous testing of the state backend are available as retainers, scoped separately from the build.
- Upgrades cover the database, storage and Pulumi CLI versions you run, with changes tested before they reach production stacks.
- Ask any provider to confirm in writing who handles security patches, incident response and restore testing after handover.

