Infrastructure in the Age of AI-Driven Development

AI speeds up infrastructure work, but without enough context it can produce code that looks right and still creates security, cost, or ops issues. Adapted from Roberto Hernandez’s 2026 CodeMash talk, this post covers how to harness AI for DevOps without amplifying risk.

Infrastructure in the Age of AI-Driven Development
Photo by Erik van Dijk / Unsplash

AI is transforming how we build infrastructure. It accelerates scaffolding, reduces toil, and acts as a force multiplier for teams. But there's a catch: AI drafts faster than humans while lacking critical context. When AI generates infrastructure directly from vague intent, it optimizes for plausibility, not safety.

The result? Code that "looks right" while quietly violating security, cost, and operational standards.

This blog explores how to build infrastructure safely in an AI-driven world, drawing from real-world patterns and hands-on demonstrations with AWS CDK. The strategies presented are inspired by AWS Best Practices for CDK and CloudFormation, adapted for an AI-assisted workflow.

Note: All code examples in this article are available in the GitHub repository. The init branch contains the initial monolithic state, while the main branch shows the final modular architecture.

The Problem with Raw AI + Infrastructure as Code

Common failure modes when AI generates infrastructure without guardrails include:

  • Over-provisioned resources that balloon cloud costs
  • Overly permissive IAM policies with dangerous wildcards
  • Public exposure by default on storage and APIs
  • Inconsistent patterns across environments

Without opinionated foundations, policy gates, and human review, AI doesn't accelerate DevOps—it amplifies risk at machine speed.

The Solution: Disciplined Collaboration

The future of DevOps isn't human OR AI—it's disciplined collaboration between the two. Here's the framework:

1. Golden Paths: Opinionated Foundations

Golden paths provide a paved road for both humans and AI. They encode proven architectural decisions, security defaults, and operational standards into reusable modules or constructs.

Instead of reinventing infrastructure, teams—and AI tools—assemble systems from trusted building blocks. This shifts infrastructure from open-ended creation to safe composition.

In Practice: We organized our CDK project into domain-specific components:

build/
├── components/              # Reusable CDK constructs
│   ├── compute/            # Lambda, ECS, compute resources
│   ├── data/               # Databases, storage, data services
│   ├── networking/         # VPC, subnets, security groups
│   └── observability/      # Logging, monitoring, alarms
├── examples/               # Example stacks showing construct usage
├── environments/           # Environment-specific configurations
└── policies/               # CDK Aspects, validation rules

Each construct has a single responsibility, is self-contained, and can be reused across projects. The ApiLambdaFunction construct, for example, handles Lambda creation with proper IAM roles, logging, and configuration—but doesn't touch API Gateway. That's a separate construct that composes with it.

2. Thin Layers: AI Composes, Not Designs

Thin layers separate assembly from architecture. AI is allowed to compose infrastructure using pre-approved modules, but it never invents core patterns, security models, or topology.

The design decisions live in versioned, reviewed building blocks owned by the platform team. This keeps AI in its strength zone—wiring and repetition—while humans remain accountable for system design and risk.

In Practice: Our main stack went from 191 lines of monolithic code to clean composition:

class TicTacToeStack(Stack):
    def __init__(self, scope: Construct, construct_id: str, config: dict, **kwargs):
        super().__init__(scope, construct_id, **kwargs)

        # AI composes, humans designed the components
        game_lambda = ApiLambdaFunction(
            self, "GameFunction",
            function_name="TicTacToeGame",
            code_path=str(project_root / "server"),
            handler="lambda_function.lambda_handler",
            memory_size=config["lambda"]["memory_size"],
            timeout=config["lambda"]["timeout"],
        )

        api = RestApiGateway(
            self, "GameAPI",
            api_name="TicTacToeAPI",
            lambda_function=game_lambda.function,
            resource_path="game",
            allowed_methods=["POST"],
        )

        website = StaticWebsiteBucket(
            self, "Website",
            source_path=str(project_root / "client"),
            removal_policy=config["s3"]["removal_policy"],
        )

AI can wire these components together, but the components themselves encode all the important decisions.

3. Spec-First Prompts: Intent Before Code

Spec-first prompts force clarity before generation. Instead of asking AI to "create infrastructure," teams describe intent, constraints, and expectations in a structured way.

Bad Prompts:

  • "Create the infra for a worker"
  • "Build this infrastructure using AWS CLI"
  • "Set up a database for my app"

Good Spec:

Workload: event-driven worker
Runtime: Python
Trigger: managed queue service
Networking: private only, no inbound access
Scaling: max concurrency capped
Secrets: managed secret store only
Logging: centralized with 30-day retention

When intent is explicit, AI outputs become repeatable, reviewable, and safer.

In Practice: We created AI instruction files that guide infrastructure development:

What AI Can Do:

  • Compose stacks using pre-approved components from components/
  • Create example stacks in examples/ that demonstrate patterns
  • Refactor monolithic stacks into compositions of existing components
  • Add environment configurations in environments/

What AI Cannot Do:

  • Create new components or modify existing components
  • Invent new infrastructure patterns or architectures
  • Hard-code environment-specific values in stacks
  • Deploy changes without validation
  • Modify production configuration without review

4. Locked Patterns: Reduce Freedom to Increase Speed

Locked patterns intentionally limit infrastructure choices to a small set of approved options. By constraining regions, instance types, networking models, and exposure patterns, teams remove entire classes of mistakes before they can happen.

In Practice: Our constraints document defines hard rules:

Structural Constraints:

Allowed:

  • build/components/compute/api_lambda_function.py
  • build/components/data/website_bucket.py

Forbidden:

  • build/api_lambda_function.py (wrong location)
  • build/components/lambda_and_api.py (mixed concerns)

One Construct Per File:

Each file MUST contain exactly one primary construct class. No "kitchen sink" files with multiple unrelated constructs.

This reduces cognitive load for humans and eliminates AI hallucinations.

5. Configuration-Driven Environments

All environment differences must live in configuration files, not code:

{
  "environment": "dev",
  "lambda": {
    "memory_size": 128,
    "timeout": 10,
    "log_retention_days": 7
  },
  "s3": {
    "removal_policy": "DESTROY",
    "auto_delete_objects": true
  }
}

Production uses the same code with different configuration:

{
  "environment": "prod",
  "lambda": {
    "memory_size": 512,
    "timeout": 60,
    "log_retention_days": 90
  },
  "s3": {
    "removal_policy": "RETAIN",
    "auto_delete_objects": false
  }
}

6. Policy Gates: CI Enforces Reality

Policy gates turn intent into enforceable rules. No matter who—or what—generates infrastructure code, CI becomes the final authority. Security, cost, compliance, and architectural standards are validated automatically before anything can be deployed.

In Practice: We implemented CDK Aspects that run during cdk synth:

@jsii.implements(IAspect)
class SecurityValidationAspect:
    def visit(self, node: IConstruct) -> None:
        if isinstance(node, iam.CfnPolicy):
            self._validate_iam_policy(node)

    def _validate_iam_policy(self, node):
        # Detect overly permissive wildcards
        if "*" in policy_actions:
            Annotations.of(node).add_error(
                "IAM policy contains wildcard action '*' which is overly permissive"
            )

Our validation suite includes:

Aspect What It Validates
SecurityValidationAspect No wildcard IAM, explicit public access, Lambda roles
TaggingValidationAspect Required Environment/Project tags on all resources
LoggingValidationAspect CloudWatch Logs enabled with retention configured

When validation fails, deployment is blocked:

❌ [error] at TicTacToeStack/BadPolicy:
    IAM policy contains wildcard action '*' which is overly permissive

7. Known Good Examples

Known good examples give AI something safe to imitate. By providing real, production-approved reference implementations, teams guide AI toward patterns that already meet standards.

Pattern Characteristics (implicit, not negotiable):

  • Private networking
  • Encrypted storage
  • Centralized logs + metrics
  • Bounded scaling
  • No public access by default

"Give AI one good example, and it will repeat it forever."

In Practice: We created example stacks that demonstrate proper composition:

class LambdaApiStack(Stack):
    """Example stack showing Lambda + API Gateway + S3 static website pattern."""

    def __init__(self, scope: Construct, construct_id: str, config: dict, **kwargs):
        # Full working example that AI can learn from
        ...

The Journey: From Monolith to Modular

Our demonstration followed four key steps. You can visualize the complete transformation by comparing the init branch (monolithic starting point) with the main branch (final modular architecture) in the GitHub repository.

Step 1: Build the Foundation

Created a monolithic CDK stack with Lambda, API Gateway, and S3. This works, but everything is tightly coupled and hard to reuse or modify safely.

Step 2: Establish AI Guidelines

Created instruction files and constraints that define:

  • Target architecture
  • What AI can and cannot do
  • Refactoring workflow
  • Code quality standards
  • Security requirements

Step 3: AI-Guided Refactoring

Using the guidelines, we refactored the monolithic stack into modular components. AI followed the constraints during refactoring, resulting in:

  • 26% reduction in stack code
  • 3 reusable components
  • Configuration-driven environments
  • Zero changes to deployed infrastructure

Step 4: Automated Validation

Added CDK Aspects that automatically enforce:

  • Security policies
  • Tagging requirements
  • Logging configuration

Validation runs on every cdk synth, catching issues before deployment.

Real-World Success Story

Teams using this approach will have achieved:

  • Opinionated CDK constructs that encode best practices
  • AI used only for composition, never for core design
  • Ephemeral PR environments for validation
  • Policy gates enforced in CI that block bad changes

The infrastructure matches expectations on the first review, passes policy checks, and ships faster—because intent was defined before code existed.

The End Goal

The goal isn't to let AI run infrastructure—it's to let AI move fast inside boundaries we trust:

  • Humans define intent, constraints, and accountability
  • Platforms enforce consistency and safety
  • AI accelerates execution

When these roles are clear, teams ship faster with fewer incidents, and infrastructure becomes more reliable as AI adoption increases.

Beyond AWS CDK

While this blog demonstrates these patterns using AWS CDK, the strategies apply universally across Infrastructure as Code tools:

  • Terraform: Use modules as your golden path components, enforce policies with Sentinel or OPA, and validate with terraform plan
  • Bicep/ARM: Create reusable modules, use Azure Policy for guardrails, and leverage what-if deployments for validation
  • CloudFormation: Build nested stacks and custom resources as components, use CloudFormation Guard for policy enforcement
  • Pulumi: Apply the same modular component patterns with your preferred programming language

The principles remain constant: golden paths, thin layers, spec-first prompts, locked patterns, policy gates, and known good examples. The implementation details change, but the strategy of disciplined AI collaboration works regardless of your IaC tool of choice.


Resources


The future of DevOps isn't human or AI—it's disciplined collaboration between the two.