High-performance and highly available VPS/VDS with automatic installation and full root access to the OS. The ordered resources are guaranteed to be reserved for you.
Fortify your operational continuity with our resilient disaster recovery solutions, ensuring swift recovery and minimal downtime in the face of unforeseen challenges.
IaC Explained: Why “Coding Infrastructure” Matters — and What It Changes
Almost everyone has seen this situation: something works in your infrastructure, but nobody fully understands why. That’s when the sacred phrase appears: “Don’t touch it.” The problem is, infrastructure will change anyway — new services, upgrades, scaling, security, costs — and sooner or later “don’t touch it” stops being an option.
Imagine a non-trivial, but very real example. You have a small product and you launch a promotion: “all new users get free access for 48 hours.” Traffic spikes, marketing is happy — and then the first worrying message shows up: “why can’t some people open the site?” You investigate and discover that a few weeks ago someone “slightly adjusted” a network rule and “temporarily” raised limits on one component, but not on another. Everything looked fine because load was lower. Under peak traffic, the invisible mismatch finally surfaces.
At that point it becomes clear: the issue isn’t that you “clicked the wrong thing.” The issue is that your infrastructure lived as a collection of manual actions and local decisions. It wasn’t described as a system you can reproduce, validate, and change in a controlled way.
There are two ways to manage infrastructure.
The first is manual: open the console, click resources into existence, tweak settings, leave a note like “this is how we did it last time,” and hope nobody forgets Step #7. It works… as long as infrastructure is small and one person touches it. But once you have a team, multiple environments, and regular change, the manual approach becomes a risk. Not necessarily “instant catastrophe,” but a steady stream of small surprises: test behaves one way, prod behaves another; logging wasn’t enabled somewhere; something was left publicly accessible; a parameter changed and nobody remembers when. Good processes (like documenting every change) can reduce the pain — but in reality something always gets missed, especially during incident firefighting and other time-critical fixes.
The second approach is Infrastructure as Code (IaC): you describe infrastructure as code, store it in a repository, and apply changes the way you apply application changes — with history, reviews, checks, and repeatable steps. Infrastructure stops being “a set of clicks” and becomes a reproducible configuration. If you need to rebuild an environment or expand an existing one, you don’t rely on memory — you repeat a defined process.
What does that change in practice?
First: repeatability. A new region, a new project, a test environment, an experimental sandbox — none of that requires manual rituals. If infrastructure is defined in code, results are consistent, which means fewer accidental differences and fewer “it only breaks in prod” situations.
Second: change control. With manual work, infrastructure changes quietly: someone “tweaks something,” forgets, and a month later you’re wondering why behavior is different. With IaC, changes are visible: there’s history, context, and review. Even when someone makes a mistake, you can catch it earlier — and roll it back more safely.
Third: operational scalability. As the number of resources grows, lack of standards turns everything into a collection of one-off decisions: different rules in different places, inconsistent settings across identical services, and “special cases” nobody enjoys maintaining. IaC helps you keep a shared template and reduces the number of snowflakes that are painful to operate later.
And finally, IaC changes the culture: infrastructure starts living by the same rules as application code. Smaller, cleaner changes. Predictable outcomes. Fewer “hot” manual edits. Less dependency on the one person who “remembers how it works.”
One important honesty note: IaC isn’t a magic wand. It introduces its own concepts (state, change ordering, environments), and teams need time to learn them. But over time, IaC almost always wins — because it removes the biggest source of chaos: infrastructure as a pile of ad-hoc actions.
Terraform and OpenTofu: Declarative IaC, State, and the Module Ecosystem
If IaC is “infrastructure as code,” then Terraform (and its fork OpenTofu) is the most recognizable way to do IaC in a declarative style. Declarative here means a simple idea: you describe what the end state should look like, and the tool figures out the steps needed to get the infrastructure to that state.
In practice, it feels like a “define → plan → apply” workflow. You declare the desired state of resources, Terraform/OpenTofu compares it to what exists today, and produces a change plan: what to create, what to modify, what to delete. That reduces manual busywork and makes changes more predictable — you can see what will happen before you ever hit “go.”
But there’s a core component you have to treat seriously — otherwise IaC quickly becomes painful: state.
State is the file (or backend storage) where the tool keeps its “memory” of what it created and what it looks like. This isn’t just a convenience. Without state, Terraform/OpenTofu can’t reliably determine which resources it owns and what changes are required. So state is both a strength and a high-attention area: you can’t lose it, you can’t let it live “wherever,” and you can’t treat it as something temporary.
In plain terms, state is your control ledger. It helps you:
Understand which real-world resources correspond to your code
Make safe changes without accidentally creating duplicates
Track dependencies and apply changes in the right order
This is also where one of Terraform/OpenTofu’s biggest advantages becomes clear: a massive ecosystem has grown around this approach.
Providers connect Terraform/OpenTofu to a wide range of platforms and services — clouds, networking, databases, queues, observability — all through one configuration language. Modules let you avoid rewriting the same patterns repeatedly: you define a reusable template (a standard VPC, a standard cluster, a standard set of access policies) and apply it across projects. Modules also help teams standardize: instead of “everyone did it their own way,” you get a consistent baseline.
That’s why Terraform/OpenTofu is often chosen as a universal default: it fits team workflows well, makes changes predictable, and comes with an abundance of ready-made building blocks. The trade-off is discipline: state must be controlled, changes should go through a proper process, and modules shouldn’t become black boxes nobody understands.
Next, we’ll look at the second approach: Pulumi. It solves the same IaC problem, but does it through general-purpose programming languages — and that brings a different philosophy: fewer declarative “templates,” more real code.
Pulumi: IaC in General-Purpose Programming Languages
Terraform/OpenTofu is often chosen for its “clean geometry”: define the desired end state, review the plan, apply. It feels like a blueprint. Pulumi is a different mindset: infrastructure is described as a program in a real programming language, and you express not only “what it should look like,” but also “the rules by which it gets created.”
To feel the difference, imagine a web project with multiple sites — not a single monolith, but a set of microsites and landing pages for different products: different domains, different caching rules, separate dev/stage/prod environments, and sometimes their own queues, IAM roles, and small exceptions. In a declarative world you can solve this too — but once you have lots of conditions (“promo gets X,” “main product gets Y,” “enable feature A in one region but not another”), configurations can grow messy and start looking like an attempt to express program logic using a tool that isn’t quite designed for it.
Pulumi tends to feel more natural in that shape. Need to repeat a pattern 30 times? Use a loop. Need branching rules and conditionals? Write them as code. Need clean, reusable building blocks? Extract them into functions and modules the same way you would in software engineering. The result is infrastructure not as a pile of “descriptions,” but as a maintainable codebase with a clear structure.
Where Pulumi Beats Terraform/OpenTofu — and Where It’s the Other Way Around
The difference between Pulumi and Terraform/OpenTofu usually isn’t about “which one is better.” It’s about how your infrastructure is shaped — and how much repetition, conditional logic, and edge cases you actually have.
EU Cloud Infrastructure You Control
Run production workloads on dedicated resources across EU data centres. Transparent pricing, no hidden costs.
Full control over compute, storage, and networking.
To make this easier to compare, here’s a table showing where each approach tends to feel more comfortable in practice:
Scenario
Pulumi is often more convenient
Terraform/OpenTofu is often more convenient
Lots of repetition with nuances (sites, domains, rules, environments)
When you want to express it as an infrastructure “generator”
When it fits cleanly into standard modules without complex logic
Complex conditions and branching
When the logic starts to look like a real program
When conditions are minimal and it’s easier to keep configs declarative
Typing / reuse / testability
When you want to apply software engineering practices (types, refactoring, tests)
When simplicity and “readability at a glance” matters most
Hiring and standardization
When the team is strong in software development and ready to maintain code
When you want a “market standard” with lots of ready-made modules
Change review
When the team is used to reviewing logic as code
When you want the most direct, transparent diff of configuration
If the table isn’t enough, let’s go back to the example with multiple sites and landing pages. If you’re running dozens of campaigns with different domains, different caching rules, separate environments, and lots of “if/then” logic, Pulumi often produces a cleaner picture: you define a “site template” once and then generate infrastructure by rules — like a construction kit. You can do this in Terraform/OpenTofu too, but once conditions start piling up, it often feels like you’re forcing program logic into the wrong tool — configs grow and become harder to maintain.
If the opposite is true — you have one primary site, a couple of standard environments, and everything fits neatly into clear modules without tricky logic — Terraform/OpenTofu is usually simpler: less “code,” more predictable declarative configuration, easier to operate in a larger team, and easier to hire people with experience.
And regardless of which tool you choose, the same reality hits everyone: IaC speeds up change, which means it also increases the cost of mistakes. So the next logical step is to look at the common places where teams most often shoot themselves in the foot.
Common IaC Mistakes: State, Secrets, Drift, Review, and Environments
No matter which tool you use — Terraform/OpenTofu or Pulumi — IaC comes with one superpower and one risk. The superpower: you can change infrastructure quickly and repeatably. The risk: you can make an expensive mistake just as quickly and repeatably. And most of the time, the mistake won’t be “clever” — it’ll be painfully basic.
1) State. In IaC, state is the memory of what was created and what it looks like. If state is stored locally, without locking and backups, you’ll eventually hit parallel-change conflicts or “reality loss,” where the tool can no longer confidently tell what it controls. The outcome is usually unpleasant: plans that unexpectedly recreate resources or try to “fix” something nobody broke. That’s why state should be centralized, protected, and locked — not for formality, but for predictability.
2) Secrets. Secrets leak in extremely boring ways: committed to a repo, printed in pipeline logs, stored in unprotected variables, “temporarily” passed into a module and never removed. A special case is when secrets end up in state — then the state itself becomes a highly sensitive artifact that must be guarded like production access. The rule of thumb is simple: secrets should live in purpose-built systems, and IaC should consume them in a way that doesn’t turn them into public garbage in logs or state files.
3) Drift (code vs. reality). Drift appears every time someone “quickly fixes it in the console.” In the moment it feels like a rescue. But then IaC detects that reality differs from the declared configuration and tries to bring it back “as code.” Best case, you get a surprising diff and an argument about “why is it trying to roll this back?” Worst case, you apply and break the very manual fix you relied on. Drift is solved with discipline: either you change things through IaC, or you immediately reflect any manual change back into code so there is only one source of truth.
4) Review. With IaC, you don’t just review code — you review consequences. A single line can trigger a resource replacement, downtime, data loss, or a migration “right now.” The healthiest process is to review the plan before applying: what will be created, changed, and destroyed. Reviewing “the code” without understanding the actual infrastructure diff is a common cause of nasty surprises.
5) Environments. When dev/stage/prod differ through random parameters and live in one shared “pool,” the classic story becomes inevitable: “we meant to fix test, but touched prod.” In practice this shows up as shared state, mixed variables, unclear boundaries between environments, and unclear permissions. In IaC, environments should be separated so it’s hard to apply changes to the wrong place — and so changes remain predictable.
If we summarize: IaC really does bring order — but only if you keep five things under control: state, secrets, drift, review, and environments. And this layer matters equally for Terraform/OpenTofu and Pulumi, because the root cause here is rarely the tool — it’s process and discipline.
How to Choose a Tool: Criteria, Use Cases, and Trade-Offs
After comparing Terraform/OpenTofu and Pulumi, it’s easy to slide into “let’s pick the trendiest one.” But in IaC, trends don’t help. A tool either fits your workflow and speeds things up — or it forces the team into constant workarounds.
What does your infrastructure look like? If you mostly have repeatable building blocks (networking, clusters, databases, roles, standard environments) and you want to assemble them like a kit of well-defined parts, Terraform/OpenTofu usually feels natural. The declarative model works best when you know what the end state should be and you want a stable “plan → review → apply” process.
If your infrastructure looks more like a system with lots of conditions and “same-but-different” repetitions — for example, dozens of microsites and landing pages, multiple domains, different content delivery rules, different access policies, different enabled services — Pulumi often becomes the more comfortable choice. It’s easier to express rules as code: generate repetitive resources, branch logic, reuse functions, and keep infrastructure as a coherent codebase.
Who will maintain it?
Terraform/OpenTofu is easier to roll out in teams where IaC needs to be highly transparent: someone can open the configs and understand what’s happening “at a glance,” without learning the project’s code architecture. It also benefits from a huge ecosystem of modules and practitioners, which lowers the adoption barrier.
Pulumi demands a more developer-oriented mindset. You’re not just “declaring resources” — you’re maintaining a project: structure, style, dependencies, and logic reviews. For a strong engineering team, that’s a feature (you can build clean, flexible abstractions). For a team where IaC is more of a necessary ops component, it can become additional overhead.
What risk are you willing to accept?
It’s worth being honest: choosing a tool doesn’t remove the core IaC failure modes. State, secrets, drift, environments, and review can break in any approach — because these are process problems, not syntax problems. The best tool is the one that makes it easiest for your team to keep discipline and avoid “quick manual fixes.”
If we compress it into a quick cheat sheet:
Choose Terraform/OpenTofu if you want a widely understood, modular, industry-standard approach and your infrastructure is mostly conventional.
Choose Pulumi if you have lots of conditional logic and generation, and you want to treat infrastructure as a software product — and your team is ready to maintain it like a real codebase.
The bigger point is that you’re not just choosing a “tool” — you’re choosing a change-management style. One style is closer to blueprints and standard blocks; the other is closer to programmatic assembly by rules.
Conclusion
Infrastructure as Code is how you stop living in “don’t touch it, it works” mode. Infrastructure becomes reproducible, changes become visible, and outcomes become predictable: you can recreate environments, understand what is changing and why, and avoid relying on the memory of a single person.
And the most important point: IaC doesn’t “save you” by itself. It simply makes change fast and repeatable — which amplifies both order and mistakes. Real value appears when the basics are in place: solid state management, careful handling of secrets, no manual changes that bypass code, clearly separated environments, and reviews not only of the code, but of the actual change plan.
Subscribe to our newsletter to get articles and news
Cookie consent
This site uses cookies to ensure it works properly and to track how you use it. By clicking 'Accept', you agree to these technologies. For more details, please see our Privacy Policy and Cookies Policy
Functional
Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes.The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.