Why manual edits in the console break Pulumi infrastructure
Pulumi stores a state file that records the actual position of resources and compares it with the description in code.
The console knows nothing about this file: an engineer manually expands a disk, opens a port, or renames a database, and the state silently drifts away from the code.
The next run either rolls back that change or brings a discrepancy into the change plan — and both options undermine trust in the process.
This is how configuration drift works: any manual intervention lives outside code and outside history. It does not pass validation, does not get reviewed, and is not reproduced when recreating an environment.
A month later, no one remembers why the rule appeared or whether it can be removed without consequences.
Then environments diverge: after several such changes, the test contour stops being a copy of production, and the difference surfaces at release, not during checks.
Rollback also stops working — the previous version cannot be deployed because no one has described the actual state. Before every release, inventory has to be collected manually, comparing the console with code and hoping nothing was missed.
This is closed by infrastructure as code: changes only through review and application from code, import of existing resources, regular reconciliation of actual state with the described state.
Below is how we build such a contour so drift is caught before release, and the environment is raised from code without manual assembly.
Measurable effects: rollout speed, environment recovery, drift
Translating infrastructure into a code description on Pulumi changes not only the way edits are made, but also how often the team decides to make them.
When contour state is assembled from a single description rather than reproduced manually, the cost of change falls: an edit goes through review like ordinary code, not as an operation in the cloud console.
What we record as a measurable result:
- Change rollout speed — a typical change goes from commit to application across all contours in minutes; manual steps through consoles leave the process.
- Environment reproducibility — test and production contours differ only in parameters: same network rules, access roles, image versions.
- Environment recovery — an environment is raised from the description from scratch, so the result does not depend on whether anyone remembers the sequence of actions.
- Drift — a discrepancy between the description and actual state is visible during a plan run; a manual edit either enters the description or is rolled back.
- Change frequency — minor edits stop requiring maintenance windows, and rollback to the previous description takes one operation.
The limitation is lifted not from infrastructure but from the team: engineers stop being afraid to touch the production contour because every change has a verifiable description and a path back. Next we show how such a contour is set up and what remains with the customer after handover.
Pulumi vs. provider templates and manual edits
Choosing an infrastructure approach is not about syntax, but about who and what will pay for changes later. Below are four options that teams realistically choose between.
The first stand is fastest to assemble manually, and on one environment that is tolerable. When there are three or four environments and they differ by a couple of parameters, maintenance turns into manual reconciliation: the discrepancy surfaces during an incident.
| Approach | When it fits | Limitation | What to keep with your team |
|---|---|---|---|
| Edits in the provider console | prototype, one environment | state is not recorded anywhere, stand repetition is manual | instructions and stand reconciliation |
| Provider templates | typical resources without complex logic | no loops or branches, blocks are copied | template branches for each environment |
| Declarative language with a state file | a single snapshot of infrastructure, many providers | requires its own abstraction layer and knowledge of the description language | modules and order of applying changes |
| Code in a general-purpose language | the team writes in Python, TypeScript, or Go, logic matters | code requires tests, validation, and naming rules | module libraries and tests |
A general-purpose language removes the main pain of templates: parameterization is done with functions and loops instead of copying blocks, while the declarative description of resources and their state is preserved — this is what Pulumi is built on.
The approach is chosen based on team composition and logic complexity, not on how trendy the tool is.
How we implement infrastructure management from code
Managed infrastructure starts not with code but with honest inventory: until every resource with dependencies and owner is written down, any environment description reproduces accumulated drift. That is why our stage order is fixed — each next stage relies on the result of the previous one.
- Resource inventory — we go through accounts and projects, collect real entities, their relationships, tags, and owners. The output is a registry against which we verify every subsequent change.
- Resource and dependency schema — we lay out the registry by layers: network, data, compute, access. We determine the creation order so that relationships do not turn into closed loops.
- Environment description — we separate environments by parameters and separate value sets, not by configuration copies. There is one template, environment differences are set by variables, so the environment is raised reproducibly.
- State and secrets setup — we move state to shared storage with locking so parallel runs do not overwrite each other's changes; secrets go to encrypted storage, and only references to them remain in the repository.
- Change plan validation — every edit first shows what will be created, changed, and deleted. Deletion of resources with data is allowed only after explicit review and confirmation.
- Handover to the team — review regulations, local run instructions, access separation, and the procedure for rollback to the previous state.
We work on Pulumi in the same sequence — the description language is chosen for the customer's team.
The readiness criterion is one: the environment deploys from scratch with one command in minutes, not days, and the result is the same for the developer, tester, and in production.
Artifacts and regulations: description, state, access
We hand over not a set of scripts but a kit that the customer's team uses to manage infrastructure on its own. Each artifact covers its own class of questions: what is deployed, who can change it and how, how to return the previous state if a change turns out unsuccessful.
Everything lies in the customer's repository and is versioned together with code — without verbal agreements and "knowledge in one engineer's head."
- Resource description structure. A single template for each stack: purpose, owner, environment, external dependencies. A new engineer understands the composition from the description without reading the entire configuration.
- Resource schema. A map of relationships between components: what depends on what, where shared networks and storages are, what will be deleted along with a parent resource.
- Access policies. Separation of roles for reading, preliminary plan, and application; separate permissions for test and production contours; manual edits in the cloud panel are closed.
- Secrets management. Keys and passwords are not stored in the repository — only references to protected storage, role-based issuance, and a rotation regulation.
- Change regulation. Any change goes through a merge request with mandatory review of the plan before application: you can see what will be added, changed, or deleted.
- Rollback rules. Version history of the description and procedure for returning to the previous state, including cases when rollback requires manual steps.
- Environment documentation. How to raise a copy of the contour for validation, which checks run automatically before application.
Plus a short local run instruction and an overview recording of the walkthrough — the team repeats a typical change using it without contacting us.
Case: drift of three environments before and after moving to code
Before: three contours that lived their own lives
Infrastructure of three environments — development, pre-production, and production — grew with the product but was managed manually.
An engineer entered the cloud provider panel, added a load balancer rule, raised a database, changed limits — and recorded it, if at all, only in chat.
Over several months, the contours diverged: some network settings and access rights differed, and reproducing production in the test environment was no longer possible.
The cost of the discrepancy turned out to be not cosmetic. An incident in production took longer to investigate because the cause was found in a manual edit from a month earlier, and environment recovery after failure took up to six hours.
The release was accompanied by more than forty manual operations — and any of them could go to the wrong contour.
After: one description for all three environments
Infrastructure was moved to code on Pulumi: topology is described once, and contour differences are moved into parameters — node size, replica count, access level.
Changes pass validation like ordinary code and remain in history, so the question "who changed the rule and when" is closed in a minute, and a new environment is raised as a copy of the description, without manual assembly from memory.
After two months of operation in the new mode, the picture is this: environment recovery time after failure decreased from six hours to 25 minutes, manual operations at release went from more than forty to three, and discrepancies between contours are detected by automatic reconciliation within an hour instead of eyeballing.
Rollback to the previous state is one operation with a predictable result, without "put it back the way it was."
What to do if infrastructure is already deployed outside Pulumi
If infrastructure is already deployed — manually or with another tool — there is no need to recreate it: Pulumi accepts existing objects under management.
Importing resources into the description binds a real object to code: the identifier enters the state file, while the object itself stays in place. The nuance is that only the reference is transferred — actual parameters must be described in code exactly as they are now.
Otherwise, the first run will try to catch up with the description: change settings, recreate a resource, or bring it down.
Therefore, transferring existing resources begins with capturing the actual state — it enters the code without edits, and changes are made as a separate step and a separate run.
| Option | When it fits | Limitations |
|---|---|---|
| Full import | One contour, simple dependencies, an up-to-date resource schema available | Long inventory; an error in a parameter leads to recreating the object |
| Gradual transfer by contour | Multiple environments, critical production, controlled pace matters | Two sources of truth live longer, ownership regulation is needed |
| Parallel management | A large legacy part that cannot be stopped | Risk of conflict over the same object, strict separation is required |
The description state is the point of truth, and each object must have one owner: if two descriptions reference the same resource, they begin to pull its settings back and forth.
Parallel management is justified only as a temporary measure — with separation by resource types and a deadline after which only one description remains.
Technical doubts: state, secrets, rollback
Before agreeing on work, technical customers ask the same questions: where infrastructure state is stored, what happens if access is lost, how environments are separated, and how safe it is to roll back changes. Below are short answers that usually remove doubts at the assessment stage.
State is not an implementation detail but part of the security contour. Therefore, its placement, secret encryption, and team permissions are designed together with the infrastructure itself, rather than "additionally configured" after the first incident.
Where is state stored and what happens if access is lost?
We move state to a remote backend with locks — parallel applications do not overwrite each other. Snapshot versions are retained, so access can be restored from a previous revision rather than rebuilding state from scratch.
How are environments isolated?
Each environment is a separate stack with its own set of parameters and its own cloud account or project. Cross-references between test and production contours are prohibited, so an error in test physically cannot change production.
What to do if a change broke the infrastructure?
Every application writes history. Rollback is re-running the previous description revision or returning to an earlier state snapshot followed by reconciliation with real resources. The target recovery time is minutes, not hours of manual edits.
How is team access separated?
We grant permissions by roles: reading state, planning changes, and applying are different levels. Secrets are decrypted only by those who have the key, and all runs enter the journal with author and time.
Who maintains the description after handover?
The description remains in your repository with documentation on stack structure and release procedure. After that, your team maintains it — or we do, under a separate support agreement.
Let's discuss the task and return with an estimate and plan
To start, it is enough to describe how the infrastructure lives now: what is already managed by code, what was configured manually through the control panel, which environments are maintained, and who has access to them.
Areas that rely on text instructions and one engineer's memory should also be named — we include them in the transfer plan separately rather than finding them in the middle of work.
- scope estimate by stage: how much work is in each and where risks are concentrated;
- work plan with start order: what we begin with, what runs in parallel, when the first code-raised environment appears;
- environment separation scheme and rules for promoting changes between them;
- list of accesses and source data needed from you to start;
- readiness criteria at each stage — you accept the result by them;
- reporting format: what and how often you see during the work.
The head of the department whose infrastructure we moved to Pulumi describes the result this way: “Editing an environment stopped being an event with manual validation — now it is an ordinary change that passes validation and rolls back with one command.”
Describe the task in free form: what is deployed, what hurts, what deadlines are pressing. We will return with a scope estimate and work plan — with start order and what will be required from your team.







