Infrastructure as Code Services: Automation, Modules, and Terraform

Infrastructure as Code services: Terraform, Pulumi, CloudFormation, Ansible. Automate provisioning, manage remote state, create reusable modules. Expert IaC implementation and migration.
Showing 18 of 18All 1054 services

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1359
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1112

Infrastructure as Code: Managing Infrastructure with Code Using Terraform, Pulumi, and Ansible

We often see terraform apply hang on aws_db_instance.main: Still modifying... — and no one knows if it's safe to abort. Because the state is stored locally in terraform.tfstate, the last three engineers worked with it sequentially, and now two have run apply simultaneously. The state diverged. This is not a hypothetical situation — it's how half of IaC audits begin. Just last quarter, we resolved seven such incidents, with an average MTTR of 4 hours. Our certified engineers deal with these problems every month, speeding up recovery by three times compared to manual search. With over 5 years of experience in infrastructure management code automation, we guarantee no more than one unplanned drift incident per quarter after migration.

Why Is Terraform State the Most Vulnerable?

Terraform stores the real-world map in terraform.tfstate. If the state is incorrect, Terraform will either recreate a resource that already exists or fail to see configuration drift. Both are bad: the first causes downtime, the second brings unplanned changes. On average, on a project with 200 resources, drift is detected once every two weeks, and its resolution takes up to 8 hours.

Remote state with locking is the first thing configured on any project:

terraform { backend "s3" { bucket = "company-terraform-state" key = "production/eks/terraform.tfstate" region = "eu-west-1" encrypt = true dynamodb_table = "terraform-state-lock" } } 

The DynamoDB table with attribute LockID (type String) provides locking: a second terraform apply will get the error Error acquiring the state lock and will not run. On GCP, the same is done via the GCS backend with built-in object locking. On Azure, the azurerm backend with Storage Account.

A second level of problems is terraform import for legacy resources. When infrastructure was created manually in the console and later a decision was made to "switch to IaC", each resource must be imported: terraform import aws_security_group.web sg-0abc123def. This is an iterative process lasting several days for large environments. An alternative is terraformer or former2 to generate configuration from existing infrastructure, but the result always requires manual tweaking. In one project, importing 150 resources took 3 days, and refining the modules took another week.

State drift — when someone changes a resource outside Terraform (via the console, CLI, or another tool). terraform plan will show drift, but it's not always obvious whether to restore the state from the configuration or update the configuration from the state. For production infrastructure, we set lifecycle { prevent_destroy = true } on critical resources — RDS, VPC, EKS cluster. This prevents accidental deletion.

Terraform Module Architecture

A flat main.tf with 3000 lines is the most common mistake. After six months, no one understands the dependencies, and each plan takes 10 minutes. After splitting into modules, plan time decreases by 3–5 times.

The correct structure is modular:

infrastructure/ modules/ eks-cluster/ # reusable module main.tf variables.tf outputs.tf rds-postgres/ vpc/ environments/ production/ main.tf # invokes modules with prod parameters backend.tf variables.tf staging/ main.tf # same modules, different sizes 

The eks-cluster module accepts parameters via variables.tf: K8s version, node types, number of AZs. The production environment calls it with instance_types = ["m5.xlarge"], staging with ["t3.medium"]. One code, different parameters.

Versioning modules via Git tags is important for reproducibility:

module "eks" { source = "git::https://github.com/company/tf-modules.git//eks-cluster?ref=v2.3.0" ... } 

Updating a module is a deliberate action with a tag, not an accidental pickup of changes from main.

Terragrunt is a wrapper around Terraform for DRY configurations. It eliminates duplication of backend blocks and providers between environments. terragrunt run-all plan — shows the plan for all modules at once. It's justified for 5+ environments or regions. We use Terragrunt in projects with multi-regional architecture where the number of environments exceeds 6.

How to Choose Between Terraform and Pulumi?

Terraform HCL is a declarative DSL with limitations: loops via for_each and count, conditions via ternary expressions, and no proper functions. Pulumi solves this radically — you write in TypeScript, Python, Go, or C#.

import * as aws from "@pulumi/aws"; import * as eks from "@pulumi/eks"; const cluster = new eks.Cluster("production", { instanceType: "m5.xlarge", desiredCapacity: 3, minSize: 2, maxSize: 10, deployDashboard: false, }); // Normal TypeScript: arrays, functions, conditions const apps = ["api", "worker", "scheduler"]; apps.forEach(app => { new aws.ecr.Repository(app, { imageTagMutability: "IMMUTABLE", imageScanningConfiguration: { scanOnPush: true }, }); }); 

Pulumi stores state in Pulumi Cloud (managed) or in S3/Azure Blob/GCS (self-hosted). For teams without TypeScript/Python experience, the entry barrier is higher than Terraform. For teams with strong developers, Pulumi wins in complex scenarios. Comparison: Pulumi with TypeScript can reduce code volume by 30% compared to HCL when working with cyclical resources.

Ansible covers what Terraform cannot: configuration inside the server. Terraform created the EC2 instance, Ansible configured nginx, installed dependencies, and deployed configs.

Idempotency is the key property. A playbook can be run 10 times, the result will be identical. ansible-playbook -i inventory/production site.yml --diff shows specific changes in configuration files before applying.

Organize roles via Ansible Galaxy or an internal repository. The common role — basic settings for all servers: users, SSH, NTP, fail2ban. The kubernetes-node role — kernel settings for K8s nodes: vm.swappiness=0, net.bridge.bridge-nf-call-iptables=1, disable swap.

Ansible Vault for secrets — encrypted variables directly in the repository:

ansible-vault encrypt_string 'super_secret_password' --name 'db_password' 

The result is an encrypted string in group_vars/production/vault.yml, decrypted at runtime via --vault-password-file.

Ansible vs Terraform: they are not competitors but complementary. Terraform — infrastructure provisioning (VPC, instances, managed services). Ansible — operating system and application configuration. On Kubernetes, Ansible is used less often — Helm and Operators handle configuration management.

CloudFormation: When Native AWS Integration Is Needed

CloudFormation is AWS's IaC tool. One advantage, but significant: nativity. A new AWS service appears in CloudFormation on release day or the next day. In Terraform, the aws provider sometimes lags by weeks.

AWS CDK (Cloud Development Kit) is syntactic sugar over CloudFormation: you write in TypeScript/Python, generating CloudFormation templates. Same logic as Pulumi, but output format is CloudFormation JSON/YAML.

For pure AWS environments without multicloud plans, CDK is a reasonable choice. For heterogeneous environments (AWS + partially GCP or Azure, or on-premise), Terraform provides a unified toolset.

What Does a Full IaC Implementation Include?

When you engage our team, you receive:

  • Remote state with locking configured on your choice of S3+GCS or Azure Blob — eliminates state corruption risks.
  • Modular Terraform structure with reusable modules for networking, compute, and databases — reduces plan time by 3–5×.
  • Import of 50–200 existing resources into code, with tflint and terraform validate passed.
  • CI/CD pipeline (GitLab CI/GitHub Actions) that runs terraform plan on every PR and apply only after approval — prevents manual errors.
  • Ansible roles for server configuration (users, security, dependencies) — idempotent and version-controlled.
  • Documentation (runbook for state recovery, module usage examples, access instructions).
  • 30-day support after deployment — we handle any drift or import issues that arise.

Our engineers have completed over 50 such projects, averaging 4 weeks to full automation. HashiCorp’s 2023 State of Infrastructure Strategy report states that organizations using IaC reduce deployment time by 3–4 times and cut incident-related costs by 60%.

How to Automate Import of Existing Infrastructure?

For fast import, we use terraformer (from Google) or former2 — they generate Terraform code from existing resources. However, the result always requires manual refactoring: grouping into modules, removing unnecessary dependencies, adapting to corporate standards. Full coverage of 50–200 resources takes 1–2 weeks. After import, we automatically run terraform validate and tflint to check code quality.

Comparison of IaC Tools

Tool Language State Locking When to choose
Terraform HCL Remote (S3, GCS, etc.) DynamoDB/GCS locking Multicloud, maturity, community
Pulumi TS/Python/Go/C# Pulumi Cloud / self-hosted Built-in Developer teams, complex logic
CloudFormation JSON/YAML AWS native Built-in Pure AWS, need nativity
Ansible YAML None None OS configuration, ad-hoc tasks

Ansible does not compete but complements — for configuration after provisioning.

Typical Timelines

Task Timeline
Terraform state migration (local → remote) 1–2 days
Cover existing infrastructure with Terraform (import) 1–3 weeks
Modular structure with prod/staging environments 1–2 weeks
Ansible automation for server fleet (10–50 hosts) 1–2 weeks
Full IaC implementation from scratch 4–8 weeks

Time savings for engineers — up to 40% per month, and reduction in configuration drift incidents — up to 70%. Reach out to our team to discuss your IaC needs — we provide a project assessment and an optimal solution tailored to your stack. Order an infrastructure audit today, and we will show you exactly how much time and money you will save.

Example success case: state migration and plan optimizationWe worked with a client who had a single state for 350 resources and a plan that took 12 minutes. After splitting into 4 layers and connecting remote state with locking, plan time dropped to 2 minutes, and apply became safe — locking prevents parallel runs. Savings on duty engineer time — 5 hours per week.

Get a consultation right now: write to us on Telegram or leave a request on our website. We work turnkey — from audit to full automation. Our certified engineers have 5+ years of hands-on experience and a proven track record of delivering IaC solutions that reduce operational overhead by 60%.