X as Code
Infrastructure as Code was just the beginning. Today, almost everything can be defined, versioned, and automated as code.
Infrastructure as Code (IaC) opened the door to a new way of thinking: if servers and networks can be described in files and committed to a repository, why not everything else? The “as Code” pattern has since expanded far beyond infrastructure - and for good reason.
Infrastructure as Code
It all started here. Tools like Terraform, Bicep, and Pulumi let you describe your cloud resources in declarative files. The result is reproducible environments, version-controlled changes, and no more “it works in staging” mysteries caused by manual drift.
Other tools - such as Ansible - can help automate processes across a larger fleet of machines. The goal is typically to increase speed and reduce the risk of human error.
The choice of tool often comes down to preference, and there are pros and cons to every approach. In a pure Azure environment, Bicep is often an excellent choice - but many opt for Terraform because it is platform-agnostic or because it is considered the most widely adopted solution.
Configuration as Code
Application configuration managed through files in source control - rather than environment-specific dashboards or manual settings. Kubernetes ConfigMaps, Helm values files, and .env-driven pipelines all follow this pattern. Changes are traceable and reversible.
The ability to distinguish between infrastructure and configuration can be decisive for how smoothly an IaC implementation goes. The starting point is that everything should be defined as code - but that does not mean everything has to be applied at once. Trying to pack too much configuration into the raw infrastructure definition often leads to catch-22 situations where provisioning fails because dependencies are not yet in place. A common cause of long, difficult IaC journeys is a lack of focus on where infrastructure ends and configuration begins.
Pipeline as Code
CI/CD pipelines defined in YAML or similar formats alongside the application code. Azure Pipelines, GitHub Actions, and GitLab CI all follow this model. The pipeline is part of the codebase - reviewed, versioned, and deployed like everything else.
There are a number of different approaches to structuring pipelines for building, testing, and deploying across environments. Company culture, governance, and risk appetite all play a significant role in determining the best solution for a given situation. The tooling also evolves continuously and can influence the choices you make.
There are many benefits to using pipelines - and one of the more advanced ones is the ability to significantly reduce access to production environments and secrets by making the pipeline the only path to production.
Policy as Code
Cloud environments are a source of enormous opportunity - and therefore also of significant risk.
Security and compliance rules can be defined as code and enforced automatically and continuously. Features like Azure Policy let platform owners define the boundaries. This makes it possible to determine in advance what is and is not permitted in a deployment, before anything reaches production.
Policies can, however, also create friction for other parts of the ecosystem, so they should be applied with care.
Monitoring as Code
Dashboards, alerts, and SLOs defined as code can be deployed alongside the services they observe. Grafana-as-code, Datadog monitors in Terraform, and Prometheus alerting rules are all good examples of established vendors embracing the “as Code” approach. When a service is deployed, its observability comes with it.
Documentation as Code
It may seem like a stretch - but documentation written in Markdown and stored in the repository alongside the code can solve many challenges with in-house solutions. By writing documentation using the same tools as the code itself, developers can use their normal workflow - and the documentation can be automatically published via, for example, an internal website as a valuable resource for other teams.
Architecture Decision Records (ADRs), API specifications (OpenAPI / Swagger), and all sorts of .md files can live close to the code they describe - and with a bit of discipline, documentation can be kept up to date in the same pull request.
The common thread
All of these patterns share the same benefits: version control, code review, automation, and reproducibility. When something is defined as code, it becomes auditable, shareable, and testable. The question is no longer whether to apply the pattern, but which tool fits the job.