Large Language Models: A Working Reference
How next-token prediction becomes a useful assistant, and how to evaluate and deploy one well
Defining, versioning and safely changing infrastructure with code
This reference explains infrastructure as code, the practice of describing servers, networks and cloud resources in machine-readable files that are versioned, reviewed and applied automatically. It covers the difference between declarative and imperative approaches, why idempotence makes repeated runs safe, how configuration drift creates cost and security exposure, and which tool families employers commonly ask about. The final pages turn these ideas into practice with a checklist, common mistakes and a closing review.
Start readingInfrastructure as Code: A Practical Reference
Defining, versioning and safely changing infrastructure with code
Infrastructure as code is the practice of describing computing infrastructure in files rather than building it by hand. A server, a network route, a database or a storage bucket is written down as a specification. A tool reads that specification and makes the real environment match it. The specification is the source of truth, and the running system is expected to follow it.
The idea is simple, but it changes how work gets done. Instead of clicking through a cloud console to create resources, an engineer edits a file, proposes the change, and lets an automated process apply it. The same file can produce a test environment and a production environment, so the two are much less likely to differ in ways nobody intended.
If a change cannot be written down in a file, it cannot be reviewed, repeated or rolled back with confidence.
Training material for cloud roles describes this shift as moving from manual provisioning toward repeatable, template-driven deployment. Standards for cloud engineering work likewise expect practitioners to deploy, update and remove resources using templates and to explain the benefits of this approach compared with console work. The core skill is learning to think of infrastructure as something you write, test and revise.
Once infrastructure is written as code, it can be stored in a version control system. Every change has an author, a timestamp and a description. Two people can compare the current definition with the one from last week and see exactly what moved. This is the same discipline teams already use for application source code, and it brings the same benefits.
Review is the first benefit. A proposed change can be read by a colleague before it touches a live system. Reviewers can catch a wrong region, an open firewall rule or a resource that will be deleted by accident. Rollback is the second benefit. If a change causes an outage, the team can return the definition to a known good state and reapply it, rather than trying to remember which console clicks were made.
A version history turns infrastructure from a memory test into a record anyone can read.
Audit is the third. Regulators, security teams and internal auditors often ask who changed what and when. When definitions live in version control, the answer is in the history. The workflow is not complicated, but it depends on one habit: no change goes into production by a route that by passes the file.
Infrastructure as code uses a small set of terms that appear again and again in documentation, job postings and certification exams. A resource is a single thing the tool manages, such as a virtual machine, a subnet or a load balancer. A provider is the plugin that knows how to talk to a particular platform. A module is a reusable bundle of resources that can be called from several places, much like a function in a programming language.
State is another essential term. Many tools keep a record of what they have already created so they can compare that record with the desired definition. This record is the state file. Its location, locking and protection are common topics in professional exams, because a damaged or shared state can cause resources to be duplicated or deleted.
Learn the words resource, state, plan and apply first; most later confusion comes from mixing them up.
Plan and apply describe the usual two-step workflow. The plan step shows what would change without changing anything. The apply step makes the changes. Reviewing a plan before applying it is one of the most useful habits a beginner can build.
Infrastructure as code sits within a wider set of practices grouped under cloud engineering, DevOps and platform engineering. Cloud engineers design and run environments. DevOps engineers focus on how software gets from a developer's laptop into production. Platform engineers build shared internal tooling so that application teams can deploy without handling every infrastructure detail themselves. These roles overlap, and in many organizations one person does parts of all three.
Vendor and industry certifications reflect this structure. Some focus on a single cloud platform, some on a specific tool, and some on the broader discipline. Employers also use practical assessments built around provisioning, configuration and troubleshooting tasks. Across these routes the same core competencies recur: writing definitions, managing state, automating delivery and keeping environments consistent.
Most job titles in this area describe overlapping work, so judge a role by its tasks rather than its name.
Choosing a path is easier when you know which competencies a role emphasizes. A cloud administrator may spend more time on platform services and governance. A platform engineer may spend more time on pipelines and reusable modules. The shared foundation is the ability to express infrastructure clearly in code.
Infrastructure definitions generally follow one of two paradigms. A declarative definition states the desired end result: there should be three servers of a given size in a given network. The tool works out the steps needed to reach that state. An imperative definition lists the exact steps to perform, in order: create this server, then attach that disk, then run this script.
Each paradigm suits different problems. Declarative tools are strong at provisioning, because they can compare desired and actual resources and create, update or delete only what differs. Imperative methods are often better for running a specific procedure, such as a one-time data migration or a sequence that must happen in an exact order. Choosing between them is partly a question of which question you are asking: what should exist, or what should happen.
Declarative tools describe the destination, while imperative steps describe the route.
Many teams use both. They provision the underlying resources declaratively and then configure those resources with imperative or procedural steps. Knowing where one style ends and the other begins is a practical skill that interviewers and exam writers test often.
To choose an approach for a task, it helps to compare the options against the qualities that matter. Three qualities come up most often: how easy it is to read and review, how well it handles changes over time, and how much manual judgment it demands. The table below is a teaching aid to show how the trade-offs differ, not a ranking of products.
Declarative provisioning scores well on review and change handling because the file describes the whole target. It can demand more upfront modeling. Imperative scripts are quick to write for one-off work, but they are harder to rerun safely and often need careful manual reasoning about what already exists. Configuration management sits between the two, describing the wanted settings on a machine while leaving the exact steps to the tool.
Ask what happens on the second run, because that answer exposes most of the design trade-offs.
When you weigh the options, ask what will happen the second time you run the same file. The answer reveals most of the trade-offs.
| Review | Change | Manual effort | |
|---|---|---|---|
| Declarative | ●●● | ●●● | ● |
| Imperative | ● | ●● | ●●● |
| Config mgmt | ●● | ●●● | ●● |
Good infrastructure definitions share a handful of design ideas. Reuse is one: a well-written module can build many similar environments without copying code. Parameterization is another: values such as region, size and name are passed in as inputs so one definition serves development, testing and production. Separation of concerns keeps networking, identity and application resources in distinct units so a change to one does not ripple through everything.
Security and governance belong in the design from the start. Least-privilege access, encrypted storage and restricted network paths are much easier to enforce when they are part of the definition than when they are added later by hand. Policy checks can run during review to flag risky settings before they are applied.
Parameters and modules let one well-designed definition serve many environments without copy-and-paste.
These ideas together make a definition readable and safe to change. A team that treats the code as a product, with clear inputs, clear outputs and tests, will find it far easier to evolve than one that stores a single large file no one dares to touch.
Idempotence is the property that running the same operation more than once produces the same result as running it once. A well-written definition can be applied on Monday and again on Tuesday without creating duplicate servers or undoing settings that were already correct. This matters because automation is run repeatedly: to scale out, to recover from a failure, or to retry a deployment that stopped halfway.
Without idempotence, every rerun is a gamble. A script that creates a resource each time it runs will create extra copies. A script that appends a line to a file will duplicate it. Good infrastructure tooling avoids this by checking the current state before acting, so the second run finds nothing to do.
A second run that changes nothing is the best evidence that a definition is safe to repeat.
Writing idempotent steps is a discipline. Test by running the same definition twice and confirming that the second pass reports no changes. If it reports changes, find out why before the definition reaches production.
Several core ideas overlap and reinforce one another. Idempotence depends on state: a tool can only avoid duplicates if it knows what already exists. Declarative definitions depend on idempotence: a desired state is only meaningful if reapplying it converges rather than piles up. Version control depends on both, because a history of changes is only trustworthy if each change can be applied predictably.
Drift sits where these ideas meet. Drift is the gap that opens when the real environment changes without a corresponding change in the definition. A console edit, an emergency fix or an automated process can cause it. When drift exists, the state record and the real resources disagree, and a future apply may undo a needed repair or leave an unmanaged change in place.
Most infrastructure surprises trace back to a mismatch between the definition, the recorded state and the live system.
Thinking in overlaps helps you troubleshoot. When a deployment behaves unexpectedly, ask which of these pieces failed: the definition, the state, the versioned history, or the real world.
A useful way to organize the topic is as layers, from the foundation to the top. At the base sit the physical or virtual compute, storage and network resources. Above them sit platform services such as managed databases and container clusters. Higher still are the configuration of operating systems and applications, and the delivery pipelines that move changes into each layer.
Infrastructure as code can address each layer, but different tools dominate different layers. Provisioning tools tend to manage the lower layers, while configuration tools manage the settings inside machines. Pipeline tools coordinate the sequence. Recognizing which layer a problem lives in tells you which tool and which file to examine.
Identify the layer where a problem lives before deciding which tool or file to change.
The layered view also explains why teams combine approaches. Provisioning creates the machine, configuration makes it correct, and a pipeline ensures both happen in order every time.
A common working method separates two jobs. First, provisioning creates the resources: networks, virtual machines, databases and their access rules. Second, configuration sets up what runs on those resources, such as packages, services, files and users. Each job suits a different style of tool, and keeping them distinct makes both easier to review.
A typical cycle follows four moves. The engineer defines the target resources, plans the change to see its effect, applies it, and then confirms the configuration on each machine matches the intended settings. When the cycle is repeated, the same steps produce the same environment each time.
Keep provisioning and configuration separate so a configuration mistake cannot quietly destroy a resource.
Splitting the work also limits blast radius. A mistake in a configuration script should not be able to delete a database, and a provisioning mistake should be visible in the plan before anything is changed.
Reliable teams follow a process that treats infrastructure changes the way they treat software releases. The process begins with a change request written as a modification to the code, not as a verbal instruction. It moves through automated checks for formatting, syntax and policy, then through human review, then through a plan that is examined before anything is applied.
Once the plan is accepted, the change is applied through an automated pipeline rather than from an individual laptop. The pipeline records what was applied and whether it succeeded. Verification follows, where tests confirm that the resources respond as expected. If something fails, the team can revert the code and apply the previous known good version.
Applying changes from a pipeline rather than a laptop leaves a record and removes one person's unrecorded settings.
This process is slower than clicking in a console, but it trades a small amount of time for a large reduction in surprise. Over many changes the trade usually pays off.
Following a single change from start to finish clarifies how the pieces fit. Suppose a team needs to add a storage bucket for application logs. The engineer writes a resource block with a name, region and access policy, and commits it to a branch. The commit triggers an automated check that validates the syntax and scans for risky settings such as public access.
A good change is small, reviewed, planned and verified, with the state updated at the end.
A reviewer reads the change and the generated plan. The plan shows one resource to add and no other changes. After approval, the change merges and the pipeline applies it. The state record is updated to include the new bucket, and a verification step confirms that writes succeed from the application.
Teams use several mechanisms to keep environments consistent over time. Templates and modules ensure that development, test and production are built from the same source, differing only in parameters. Locking prevents two people from applying conflicting changes to the same state at once. Remote storage of state makes the record available to the pipeline and protected from accidental loss.
Scheduled runs of the plan, without applying, can reveal drift overnight. Tagging and naming conventions make it easier to see which resources belong to which owner and project. Each of these mechanisms targets a specific way in which systems wander from their intended form.
Consistency is a combination of shared templates, locks, protected state and regular drift checks.
No single mechanism is enough on its own. Consistency comes from a combination of code, controls and regular checks.
Adoption rarely happens all at once. Many organizations begin with a single new environment, written in code from the outset, while existing systems continue to be managed by hand. Over time, the team imports existing resources into the state, so the code describes what is already running, and then migrates changes to the code path.
Each stage brings a milestone. The first milestone is a repository and a pipeline. The second is a reusable module used by more than one team. The third is routine review of plans for every change, including those made by senior staff. Maturity shows up in the habits, not only in the tools installed.
Adopt in stages, importing existing resources before changing them, so the first plan never surprises you.
Patience matters here. Importing existing resources can take careful work, and rushing it can cause a plan to delete something that was never meant to change.
Tooling choices depend on the cloud platform, the team's skills and the kind of work to be done. Some tools are cloud-neutral and describe resources across several providers. Some are tied to a single cloud and use that platform's native templating. Configuration tools focus on the settings inside operating systems and applications. Each family has strengths, and many environments use more than one.
When evaluating options, consider how mature the community is, how well the tool handles state, how it reports plans, and how it fits existing pipelines. Consider also how readable the language is for the people who will review it. A tool that few teammates can read will slow reviews and invite errors.
Learn one tool family deeply, then transfer the concepts, which carry over to other families.
Employer demand often centers on the families most widely used in job postings and certification blueprints. Learning one family well, along with the concepts that transfer, is more useful than superficial familiarity with many.
| Multi-cloud | Native | Config | |
|---|---|---|---|
| Readability | ●● | ●●● | ●● |
| State handling | ●●● | ●● | ● |
| Pipeline fit | ●●● | ●● | ●●● |
Infrastructure as code supports several common uses. Scaling is one: an autoscaling group or a set of defined replicas can grow and shrink from the same definition. Disaster recovery is another: a team that can rebuild an environment from code can bring a service back in a new region without relying on a hand-made runbook. Environment replication lets teams create short-lived test environments for every feature branch.
Security and compliance work benefits as well. Policies expressed in code can block in secure settings before they deploy, and the history gives auditors a clear record. Cost management also improves, because unused resources defined in code are easier to find and remove than resources scattered across accounts.
Scaling, recovery, testing, audit and cost control all rest on the same foundations of versioning and idempotence.
These uses depend on the earlier ideas. Scaling and recovery rely on idempotence. Auditing relies on versioning. Cost control relies on keeping the state truthful.
Configuration drift and untracked manual changes are a major source of avoidable cost, downtime and security exposure. A resource created in a console and forgotten continues to bill. A firewall rule opened to fix a problem last month may still be open. A server patched by hand may differ from its peers, so a failure appears only on that one machine.
The sources of these losses are usually ordinary. A temporary change is never reverted. An emergency fix is applied in the console and never added to the definition. A team member leaves and takes undocumented knowledge with them. Each case leaves the real environment and the record out of step.
Untracked manual changes are a quiet cost, so every emergency fix should be written back into the definition.
Estimating the scale of these losses for a specific organization requires local data. A general point holds regardless: the cheapest place to catch a drifted setting is in a plan review, not during an incident.
Preventing drift is partly a people problem. When only one person knows how the environment was built, every change depends on that person. Shared ownership spreads knowledge through reviews, documentation and rotation of on-call duties. Clear rules about who may change what, and through which path, reduce the number of undocumented edits.
Drift control also needs tools. Scheduled plan runs compare the definition with reality and report differences. Access controls limit who can change resources directly. Alerts notify the team when a resource changes outside the pipeline, so an unexpected edit is noticed quickly rather than months later.
Tools can detect drift, but only a habit of writing every change into code prevents it from coming back.
The combination matters. Tools detect drift, but a culture of writing every change back into code is what stops it from returning.
Adopting infrastructure as code forces several decisions. One is the boundary between code and console: which resources must be defined in code, and which, if any, may be created by hand in a sandbox. Another is the structure of state, including how many state files to keep and how to separate them by environment or team.
Other decisions concern ownership and review. Who approves a change to a shared network? Who may run an apply against production? How quickly must an emergency change be written back into code? Teams that answer these questions in writing avoid arguments during incidents.
Write down who may apply, who approves and how emergencies are recorded before the first incident forces the question.
Decisions about modules are also significant. A module shared widely must be stable and versioned, and changing it affects every consumer. Treating shared modules like published libraries, with release notes and compatibility checks, prevents surprises across teams.
When a change causes trouble, recovery begins with identifying the last known good version of the definition. The team reverts the code to that version and generates a plan. The plan shows what the revert will change, and reviewers confirm it before applying. Recovery is faster when rollbacks are rehearsed, because the steps are already familiar.
Some changes cannot be reversed cleanly. Deleting a database may destroy data that no version of the code can bring back. For these cases, teams add protections such as deletion locks and backups, and treat certain plan outputs as requiring extra review. Knowing which changes are reversible is part of the job.
Before any risky apply, know which changes are reversible and which need a backup or deletion lock first.
After any recovery, the team should confirm that the real environment matches the restored definition and that no drift remains from emergency fixes made during the incident.
Several mistakes appear again and again among learners and new teams. The first is treating the code as documentation only, so the real environment is changed by hand and the code slowly becomes a fiction. The second is storing secrets in plain text inside definition files, where they spread through version history. The third is applying changes without reading the plan.
Other frequent errors include putting unrelated resources in one state file, which makes every apply risky; copying a module and editing the copy, which causes versions to diverge; and skipping the idempotence test, so a rerun unexpectedly creates duplicates. Each of these is avoidable with the habits already described.
Never apply a plan you have not read, and never keep secrets in a file that lives in version history.
Recognizing these mistakes early helps you review your own work. Ask whether the code is the only way the environment changes, whether secrets are kept out of files, and whether you have read the plan before applying.
Practice builds the habits that reviewers and employers look for. A useful exercise is to take a small set of resources, define them in a template, and then apply the template to create them. Change one parameter, produce a plan, and read it before applying. Finally, delete the resources through the same definition and confirm nothing is left behind.
A second exercise is to create a deliberate drift. Change a setting in the console, then run a plan and observe how the tool reports the difference. Decide whether to revert the console change or update the code to match, and record your reasoning. This teaches the difference between the definition and reality.
Practice by creating, planning, drifting and removing a small environment, and document each step you take.
Write user documentation for your templates as you go. A short description of inputs, outputs and the apply procedure is a standard expectation in cloud engineering work and makes your code usable by others.
This reference has covered the foundations of infrastructure as code: what it means, why versioned definitions matter, how declarative and imperative thinking differ, and why idempotence makes repeated runs safe. It has also covered drift, the tooling families employers ask about, and the habits of teams that use these methods well.
To consolidate the material, review the main chain of reasoning. A definition describes the wanted state. A plan shows the difference from the recorded state. An apply makes the change, and verification confirms the result. Drift is the gap that appears when reality moves without the definition, and it is closed by writing changes back into code.
The durable skill is the cycle of define, plan, apply, verify and reconcile, which applies across every tool.
For further study, choose one cloud platform and one tool family, complete a small project, and document it. Practical experience with that cycle will teach more than any single explanation.
How next-token prediction becomes a useful assistant, and how to evaluate and deploy one well
Building, training, deploying and maintaining intelligent systems in production
Hull form, stability, propulsion, safety and the roles behind a working vessel
How internal structure, processing and service conditions decide what a material can do
Payment Successful!
Check your email for the course access link.
For quick, secure checkout on the next step
Non-Refund Policy
All course purchases on vaayaa.com are non-refundable. Since the courses are pure text with no streams, the full digital course content becomes accessible immediately after payment. Therefore, we cannot process refunds once a purchase is completed.
Please ensure you have reviewed the course details before proceeding with your purchase.