Files
nexus/sreweekly/articles/431/05-using-llms-to-generate-terraform-code.html
2026-09-12 17:23:01 +08:00

65 lines
88 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="/assets/static/src_index-b3c78705.C4pPiiRG.css">
<link rel="stylesheet" type="text/css" href="/assets/static/highlight.Dfs9RUU9.css">
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title data-rh="true">Using LLMs to Generate Terraform Code - 2025 Update</title>
<meta data-rh="true" name="description" content="An in-depth analysis using Claude, ChatGPT, and Mistral"/><meta data-rh="true" property="og:title" content="Using LLMs to Generate Terraform Code - 2025 Update"/><meta data-rh="true" property="og:description" content="An in-depth analysis using Claude, ChatGPT, and Mistral"/><meta data-rh="true" property="og:type" content="article"/><meta data-rh="true" property="og:url" content="https://terrateam.io/blog/using-llms-to-generate-terraform-code"/><meta data-rh="true" property="og:site_name" content="Terrateam"/><meta data-rh="true" property="article:published_time" content="2025-07-28T00:00:00.000Z"/><meta data-rh="true" property="article:author" content="Terrateam"/><meta data-rh="true" name="twitter:card" content="summary_large_image"/><meta data-rh="true" name="twitter:site" content="@terrateamio"/><meta data-rh="true" name="twitter:title" content="Using LLMs to Generate Terraform Code - 2025 Update"/><meta data-rh="true" name="twitter:description" content="An in-depth analysis using Claude, ChatGPT, and Mistral"/>
<link rel="canonical" href="https://terrateam.io/blog/using-llms-to-generate-terraform-code" />
<meta property="og:title" content="function title(pageContext) {
const { post } = pageContext.data;
return post?.seoTitle || post?.title || &quot;Blog Post&quot;;
}" />
<meta property="og:description" content="function description(pageContext) {
const { post } = pageContext.data;
return post?.description || &quot;Blog post from Terrateam&quot;;
}" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://terrateam.io/blog/using-llms-to-generate-terraform-code" />
<meta property="og:image" content="https://terrateam.io/og-image.png" />
<meta property="og:site_name" content="Terrateam" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@terrateamio" />
<meta name="twitter:title" content="function title(pageContext) {
const { post } = pageContext.data;
return post?.seoTitle || post?.title || &quot;Blog Post&quot;;
}" />
<meta name="twitter:description" content="function description(pageContext) {
const { post } = pageContext.data;
return post?.description || &quot;Blog post from Terrateam&quot;;
}" />
<meta name="twitter:image" content="https://terrateam.io/og-image.png" />
<link data-rh="true" rel="canonical" href="https://terrateam.io/blog/using-llms-to-generate-terraform-code"/><link data-rh="true" rel="alternate" type="application/rss+xml" title="Terrateam Blog RSS Feed" href="/rss.xml"/>
<script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Using LLMs to Generate Terraform Code - 2025 Update","description":"An in-depth analysis using Claude, ChatGPT, and Mistral","author":{"@type":"Organization","name":"Terrateam","url":"https://terrateam.io"},"publisher":{"@type":"Organization","name":"Terrateam","logo":{"@type":"ImageObject","url":"https://terrateam.io/logo.png"}},"datePublished":"2025-07-28T00:00:00.000Z","dateModified":"2025-07-28T00:00:00.000Z","mainEntityOfPage":{"@type":"WebPage","@id":"https://terrateam.io/blog/using-llms-to-generate-terraform-code"},"url":"https://terrateam.io/blog/using-llms-to-generate-terraform-code","keywords":"terraform, infrastructure, iac, security, llm, github, open-source"}</script>
<!-- Theme Init (prevents flash of wrong theme) -->
<script>(function(){var t=localStorage.getItem('theme');if(!t){t=window.matchMedia&&window.matchMedia('(prefers-color-scheme: light)').matches?'light':'dark'}document.documentElement.setAttribute('data-theme',t)})()</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-M8VVXPD7');</script>
<!-- End Google Tag Manager -->
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-M8VVXPD7"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<div id="root"><div class="min-h-screen bg-bg relative"><nav class="sticky top-0 bg-bg border-b border-theme-border z-50"><div class="max-w-7xl mx-auto px-6"><div class="flex h-16 items-center justify-between"><div class="flex-shrink-0 flex items-center"><a href="/" class="flex items-center text-text-primary"><svg viewBox="0 0 807.39 224.01" class="h-12" aria-label="Terrateam"><g fill="currentColor"><path d="M262.04,92.73l7.56.04.1-16.56,14.91.09-.1,16.56,12.83.08-.07,11.39-12.83-.08-.12,20.81c-.03,4.97,2.75,7.06,6.79,7.08,2.38.01,4.76-.39,6.53-1l2,11.92c-2.91,1.33-7.26,2.13-11.09,2.11-11.08-.07-19.21-7.05-19.14-19.37l.13-21.63-7.56-.04.07-11.39Z"></path><path d="M359.2,117.32l-.04,6.21-36.75-.22c.99,7.15,5.53,10.28,15.26,10.44,5.49.03,10.77-.97,15.23-3.01l2.52,10.88c-5.5,2.97-11.72,4.38-17.83,4.35-18.63-.11-30.37-10.32-30.27-26.99.08-14.18,9.89-26.75,26.66-26.86,14.8.09,25,8.84,25.21,25.2ZM322.89,113.59l21.32.13c-.58-6.73-4.6-9.34-9.78-9.37-6.52-.04-10.16,3.25-11.55,9.25Z"></path><path d="M372.07,93.38l14.91.09-.03,5.8.62.21c3.34-4.02,8.32-6.99,14.22-6.95h1.45s-.08,13.88-.08,13.88h-2.48c-5.49-.05-10.26,1.79-13.8,4.67l-.2,34.26-14.91-.09.31-51.86Z"></path><path d="M416.34,93.63l14.91.09-.03,5.8.62.21c3.34-4.02,8.32-6.99,14.22-6.95h1.45s-.08,13.88-.08,13.88h-2.48c-5.49-.05-10.26,1.79-13.8,4.67l-.2,34.26-14.91-.09.31-51.86Z"></path><path d="M494.19,97.6l.52-.31.02-3.21,14.91.09-.31,51.76-14.91-.09.03-4.97-.62-.21c-3.23,3.6-8.63,6.16-15.25,6.12-13.98-.08-24.88-12.05-24.79-27.06.09-15.01,11.55-26.85,26.14-26.76,6.52.04,10.96,1.93,14.26,4.64ZM494.53,127.63l.11-18.84c-3.2-2.19-7.64-3.56-12.92-3.59-7.14-.04-12.97,6.03-13.03,14.62-.05,8.49,5.71,14.73,12.85,14.78,5.28.03,10.26-1.8,12.98-6.96Z"></path><path d="M522.3,94.25l8.38.05.1-16.56,8.28.05-.1,16.56,15.32.09-.04,7.25-15.32-.09-.16,27.43c-.04,7.25,3.77,10.38,9.25,10.41,3.11.02,5.8-.28,8.19-1.3l2.03,6.43c-3.11,1.53-6.64,2.13-10.26,2.11-10.04-.06-17.56-6.42-17.49-17.7l.16-27.43-8.38-.05.04-7.25Z"></path><path d="M614.92,115.5l-.04,6.21-39.44-.24c.55,11.91,7.14,18.47,19.56,18.75,5.49.03,10.77-.97,15.23-3.01l1.72,6.74c-5.29,2.35-11.1,3.56-17,3.52-16.15-.1-27.89-10.31-27.79-26.97.08-14.18,10.2-26.75,25-26.87,13.35.08,21.28,7.89,22.75,21.88ZM576.1,114.23l30.43.18c-.36-8.49-6.44-13.5-14.31-13.54-8.49-.05-14.22,5.92-16.12,13.36Z"></path><path d="M667.8,99.25l.52-.2.02-3.93,8.28.05-.31,51.76-8.28-.05.03-5.69-.62-.31c-3.54,4.12-9.46,6.98-16.92,6.94-13.87-.08-24.88-12.05-24.79-27.06.09-15.01,11.65-26.85,26.14-26.76,7.35.04,12.31,2.25,15.91,5.27ZM668.13,131.96l.15-25.46c-3.71-3.23-9.18-5.23-15.39-5.27-10.25-.06-18.79,8.69-18.85,19.56-.06,10.77,8.37,19.72,18.62,19.78,6.31.04,12.23-2.31,15.47-8.6Z"></path><path d="M771.86,147.51l-8.28-.05.18-31.05c.06-10.15-5.09-14.52-11.4-14.56-6.31-.04-12.44,2.62-15.69,9.53.1.93.2,1.86.19,2.8l-.2,33.12-8.28-.05.2-33.12c.05-8.7-5.1-12.45-11.42-12.49-6.73-.04-13.06,2.61-16.52,9.63l-.21,35.81-8.28-.05.31-51.76,8.28.05-.04,6.52.62.21c3.65-4.53,9.98-7.71,17.95-7.66,6.52.04,12.3,3.18,15.27,9.1,4.59-5.56,11.23-8.94,19.93-8.89,9.83.06,17.66,7.46,17.57,21.84l-.18,31.05Z"></path></g><path fill="var(--color-accent)" d="M216.71,94.78c-.49-15.9-11.27-32.1-34.26-32.44h-19.15c.2-3.75-.15-6.92-.48-8.85-1.64-9.71-8.44-19.16-18.21-25.28-9.84-6.17-21.27-8.02-31.37-5.08-17.2,5.01-28.64,21.43-27.92,39.18h-14.66s0,0,0,0c-.04,0-.09,0-.13,0-13.96-.28-25.03,5.16-31.16,15.36-6.73,11.22-6.68,26.83.12,38.84,3.16,5.58,7.5,9.69,12.53,12.06.01,2.8.34,5.57,1.01,8.25,4.34,17.35,20.26,29.42,38,29.41.14,0,.29,0,.43-.01.03,6.9.47,12.73,4.36,19.43,6.01,10.35,17.06,16.55,29.55,16.59h.11c12.55,0,23.68-6.19,29.79-16.57,2.75-4.67,3.8-13.23,4.21-19.36,3.05.73,6.12,1.13,9.16,1.13,3.88,0,7.7-.61,11.32-1.84,17.85-6.07,28.77-24.5,25.81-43.2,7.53-7.17,11.27-17.74,10.96-27.63ZM94.38,62.01c-.19,0-.38,0-.57,0-.17,0-.48,0-.85-.01-.58-14.29,8.61-27.5,22.42-31.52,8.01-2.33,17.18-.8,25.16,4.21,7.94,4.98,13.45,12.48,14.73,20.07,.22,1.33.58,4.15.34,7.57-.16,2.36-.61,5.01-1.58,7.66-.72,1.97-1.71,3.93-3.11,5.78-5.97,7.89-11.38,8.95-19.29,3.8-2.96-1.93-5.59-3.9-8.13-5.81-1.72-1.29-3.42-2.56-5.16-3.77-5.3-3.68-10.98-6.72-18.79-7.66-1.62-.2-3.33-.31-5.16-.31ZM91.12,157.74c0,.17-.02.48-.04.84h-.07c-14.27,0-27.08-9.69-30.56-23.61-.35-1.39-.57-2.81-.69-4.24-.21-2.52-.07-5.09.4-7.66.83-4.5,2.66-8.97,5.46-13.08,5.28-7.74,12.99-12.96,20.62-13.94.83-.11,2.24-.24,4-.24,4.49,0,11.31.89,16.82,5.4,7.66,6.27,8.51,11.71,3.05,19.42-2.04,2.89-4.12,5.43-6.12,7.9-1.68,2.07-3.33,4.1-4.87,6.23-3.69,5.11-6.68,10.76-7.67,18.6-.18,1.39-.3,2.84-.34,4.39ZM148.65,181.8c-4.72,8.02-13.38,12.8-23.19,12.8h-.09c-9.74-.03-18.32-4.8-22.95-12.78-3.38-5.82-3.36-10.58-3.32-18.47v-2.52c0-2.41,0-4.77,0-7.06,1.2-8.57,5.35-13.68,10.82-20.41,2.08-2.56,4.24-5.21,6.43-8.3,7.88-11.13,6.43-20.87-4.45-29.78-9.78-8.01-21.9-7.44-26.66-6.83-9.76,1.26-19.47,7.7-25.96,17.22-3.13,4.59-5.27,9.57-6.39,14.65-3.3-2.25-5.5-5.34-6.76-7.58-5.4-9.54-5.49-22.34-.21-31.13,4.59-7.64,12.69-11.66,23.49-11.66,.37,0,.75,0,1.13.01.1,0,.21,0,.31,0h28.22c8.01,1.08,13.15,4.91,19.81,9.91,2.64,1.98,5.37,4.03,8.55,6.1,4.58,2.98,8.87,4.48,12.92,4.48,6.06,0,11.58-3.35,16.66-10.07,2.54-3.36,4.11-6.94,5.05-10.39h20.29c19.14.3,26.34,13.66,26.69,25.02,.33,10.61-4.01,18.47-10.18,23.2-.73.01-1.38.03-1.68.05-11.21.63-17.17-3.45-25.43-9.09-2.72-1.86-5.54-3.79-8.81-5.72-11.74-6.93-21.33-4.67-29.3,6.9-7.17,10.41-5.6,22.44-4.59,27.13,2.07,9.63,9.29,18.76,19.31,24.45,1.17.66,2.36,1.25,3.57,1.79-.31,6.46-1.3,14.7-3.28,18.07ZM177.47,158.36c-5.53,1.88-11.72,1.88-17.76.12-2.57-.75-5.12-1.82-7.57-3.21-.03-.02-.06-.03-.08-.05-8.11-4.62-13.91-11.85-15.52-19.34-.62-2.9-2.22-13,3.41-21.18,3.46-5.02,6.81-7.44,10.78-7.44,2.48,0,5.19.94,8.32,2.79,3.05,1.8,5.76,3.65,8.38,5.44,4.52,3.09,8.91,6.07,14.13,8.07,4.51,1.72,9.65,2.7,16.05,2.34.17,0,.48-.02.85-.02.05.55.05,1.11.07,1.66.44,13.63-7.98,26.37-21.07,30.83Z"></path></svg></a><a href="https://stategraph.com" target="_blank" rel="noopener noreferrer" class="ml-2 text-xs text-text-dim hover:text-accent hidden sm:inline transition-colors duration-150">by Stategraph</a></div><div class="hidden xl:flex flex-1 items-center justify-start ml-12"><div class="flex items-center space-x-1"><div class="relative"><button class="flex items-center text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150 whitespace-nowrap" aria-expanded="false" aria-haspopup="true"><span>Product</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 ml-1 transform transition-transform duration-150 "><path d="m6 9 6 6 6-6"></path></svg></button><div class="absolute top-full left-0 w-64 max-w-[90vw] bg-surface rounded-lg shadow-lg py-2 mt-1 border border-theme-border z-50 hidden" role="menu"><a href="/orchestration-engine" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg><span>Orchestration Engine</span></a><a href="/stacks" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg><span>Terrateam Stacks</span></a><a href="/product/security-and-compliance" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg><span>Security &amp; Compliance</span></a><a href="/product/deployment" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><path d="M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z"></path></svg><span>Deployment Options</span></a></div></div><div class="relative"><button class="flex items-center text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150 whitespace-nowrap" aria-expanded="false" aria-haspopup="true"><span>Use Cases</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 ml-1 transform transition-transform duration-200 "><path d="m6 9 6 6 6-6"></path></svg></button><div class="absolute top-full left-0 w-80 max-w-[90vw] bg-surface rounded-lg shadow-xl py-2 mt-1 border border-theme-border z-50 hidden" role="menu"><a href="/use-cases/scale-infrastructure" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><polyline points="22 7 13.5 15.5 8.5 10.5 2 17"></polyline><polyline points="16 7 22 7 22 13"></polyline></svg><span>IaC at Scale</span></a><a href="/use-cases/infrastructure-governance" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg><span>Governance &amp; Security</span></a><a href="/use-cases/developer-self-service" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg><span>Developer Self-Service</span></a><a href="/use-cases/drift-detection" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><path d="M22 12h-4l-3 9L9 3l-3 9H2"></path></svg><span>Drift Detection</span></a><a href="/use-cases/cost-optimization" class="flex items-center px-4 py-3 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent transition-colors duration-150"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 mr-3 text-accent"><line x1="12" x2="12" y1="2" y2="22"></line><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path></svg><span>Cost Optimization</span></a></div></div><div class="relative"><button class="flex items-center text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150 whitespace-nowrap" aria-expanded="false" aria-haspopup="true"><span>Resources</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 ml-1 transform transition-transform duration-200 "><path d="m6 9 6 6 6-6"></path></svg></button><div class="absolute top-full right-0 w-[460px] max-w-[90vw] bg-surface rounded-lg shadow-lg p-4 mt-1 border border-theme-border z-50 hidden" role="menu"><div class="grid grid-cols-2 gap-8"><div><h3 class="text-xs font-semibold text-text-dim uppercase tracking-wider mb-2 px-2">Learn</h3><div class="space-y-1"><a href="/technical-architecture" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg><span>Architecture</span></a><a href="/monorepo-at-scale" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><rect width="20" height="8" x="2" y="2" rx="2" ry="2"></rect><rect width="20" height="8" x="2" y="14" rx="2" ry="2"></rect><line x1="6" x2="6.01" y1="6" y2="6"></line><line x1="6" x2="6.01" y1="18" y2="18"></line></svg><span>Monorepos</span></a><a href="/gitops" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><line x1="6" x2="6" y1="3" y2="15"></line><circle cx="18" cy="6" r="3"></circle><circle cx="6" cy="18" r="3"></circle><path d="M18 9a9 9 0 0 1-9 9"></path></svg><span>GitOps</span></a><a href="/philosophy" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"></path><path d="M9 18h6"></path><path d="M10 22h4"></path></svg><span>Philosophy</span></a><a href="/open-source" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-3 text-accent"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg><span>Open Source</span></a><a href="/blog" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></svg><span>Blog</span></a></div></div><div><h3 class="text-xs font-semibold text-text-dim uppercase tracking-wider mb-2 px-2">Connect</h3><div class="space-y-1"><a href="/community" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><path d="M22 21v-2a4 4 0 0 0-3-3.87"></path><path d="M16 3.13a4 4 0 0 1 0 7.75"></path></svg><span>Community</span></a><a href="/case-studies" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" x2="8" y1="13" y2="13"></line><line x1="16" x2="8" y1="17" y2="17"></line><line x1="10" x2="8" y1="9" y2="9"></line></svg><span>Case Studies</span></a><a href="/support" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg><span>Support</span></a><a href="/demo" class="flex items-center px-2 py-2 text-sm text-text-muted hover:bg-bg-secondary hover:text-accent rounded-md whitespace-nowrap transition-colors duration-150 group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-accent"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg><span>Get a Demo</span></a></div></div></div></div></div><a href="https://docs.terrateam.io" target="_blank" rel="noopener noreferrer" class="text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150">Docs</a><a href="/pricing" class="text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150">Pricing</a></div></div><div class="hidden xl:flex items-center space-x-4"><button class="w-10 h-10 flex items-center justify-center rounded border border-theme-border text-text-muted" aria-label="Toggle theme"><span class="text-lg">◐</span></button><a href="https://github.com/terrateamio/terrateam" target="_blank" rel="noopener noreferrer" class="text-text-muted hover:text-accent p-2 rounded-md transition-colors duration-150" title="GitHub"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path><path d="M9 18c-4.51 2-5-2-7-2"></path></svg></a><a href="/contact" class="text-text-muted hover:text-accent py-2 px-3 text-sm font-medium rounded-md transition-colors duration-150 whitespace-nowrap border border-theme-border hover:border-accent">Book a Demo</a><a href="https://app.terrateam.io" class="bg-accent text-bg px-4 py-2 rounded-md hover:bg-accent-hover transition-colors text-sm font-semibold whitespace-nowrap uppercase tracking-wide">Get Started</a></div><div class="xl:hidden flex items-center justify-end flex-1"><button class="text-text-primary hover:text-accent" aria-label="Open menu"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-7 w-7"><line x1="4" x2="20" y1="12" y2="12"></line><line x1="4" x2="20" y1="6" y2="6"></line><line x1="4" x2="20" y1="18" y2="18"></line></svg></button></div></div></div></nav><main><article class="max-w-6xl mx-auto px-4 py-20"><div class="flex items-center justify-between mb-8"><a href="/blog" class="inline-flex items-center text-text-muted hover:text-accent"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="m12 19-7-7 7-7"></path><path d="M19 12H5"></path></svg>Back to Blog</a><a href="/rss.xml" class="inline-flex items-center px-3 py-2 text-sm font-medium text-text-muted bg-bg border border-theme-border rounded-lg hover:bg-bg-secondary hover:text-text-muted transition-colors" title="Subscribe to RSS feed"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg>RSS</a></div><header class="mb-12"><div class="flex items-center text-text-dim text-sm mb-4"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"></rect><line x1="16" x2="16" y1="2" y2="6"></line><line x1="8" x2="8" y1="2" y2="6"></line><line x1="3" x2="21" y1="10" y2="10"></line></svg><span>July 28, 2025</span><span class="mx-2">•</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg><span>mike-vanbuskirk</span></div><div class="flex items-center text-text-dim text-sm mb-4"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="M12 2H2v10l9.29 9.29c.94.94 2.48.94 3.42 0l6.58-6.58c.94-.94.94-2.48 0-3.42L12 2Z"></path><path d="M7 7h.01"></path></svg><div class="flex flex-wrap gap-2"><a href="/blog/tags/terraform" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">terraform</a><a href="/blog/tags/infrastructure" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">infrastructure</a><a href="/blog/tags/iac" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">iac</a><a href="/blog/tags/security" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">security</a><a href="/blog/tags/llm" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">llm</a><a href="/blog/tags/github" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">github</a><a href="/blog/tags/open-source" class="bg-accent-bg text-accent px-2 py-1 rounded-md hover:bg-accent-bg transition-colors text-xs">open-source</a></div></div><h1 class="text-balance max-w-4xl text-4xl font-bold text-text-primary mb-6">Using LLMs to Generate Terraform Code - 2025 Update</h1></header><div class="flex flex-col lg:flex-row gap-12"><div class="prose prose-xl prose-slate max-w-4xl flex-1"></div><aside class="hidden lg:block flex-shrink-0"><div class="bg-bg rounded-lg p-6 shadow-sm border border-theme-border sticky top-32 w-64"><div class="flex items-center mb-6"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5 text-accent mr-2"><path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path><path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path></svg><h2 class="text-lg font-semibold text-text-primary">On this page</h2></div><nav class="relative"><div class="absolute left-0 top-0 bottom-0 w-[2px] bg-gradient-to-b from-accent/20 via-theme-border to-theme-border" style="background-size:2px 8px;background-repeat:repeat-y"></div><ul class="space-y-1 relative"></ul></nav></div></aside></div></article></main><footer class="bg-bg-secondary text-text-muted border-t border-theme-border"><div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16"><div class="grid md:grid-cols-12 gap-8 mb-12"><div class="md:col-span-3"><div class="flex items-center mb-4"><img src="/logo.png" alt="Terrateam" class="h-12 logo-adaptive"/></div><p class="text-text-muted mb-6">Terrateam is the flexible GitOps orchestration engine for infrastructure as code.</p><div class="mb-6"><p class="text-text-dim text-sm font-medium mb-3">Available On</p><div class="flex items-center space-x-4"><a href="/aws-marketplace" class="inline-flex items-center bg-surface hover:bg-bg transition-colors rounded-lg px-4 py-2 border border-theme-border"><span class="text-text-muted text-sm font-medium">AWS Marketplace</span></a></div></div><div class="flex space-x-4"><a href="https://app.terrateam.io" class="inline-flex items-center px-4 py-2 bg-accent text-bg rounded-lg hover:bg-accent-hover transition-colors font-semibold"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path><circle cx="9" cy="7" r="4"></circle><line x1="19" x2="19" y1="8" y2="14"></line><line x1="22" x2="16" y1="11" y2="11"></line></svg>Register</a><a href="https://app.terrateam.io/" class="inline-flex items-center px-4 py-2 bg-surface text-text-primary rounded-lg hover:bg-bg transition-colors border border-theme-border"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" x2="3" y1="12" y2="12"></line></svg>Login</a></div></div><div class="md:col-span-9 grid md:grid-cols-4 gap-8"><div><h4 class="text-text-primary font-semibold mb-4">Product</h4><ul class="space-y-3"><li><a href="/orchestration-engine" class="hover:text-accent transition-colors">Orchestration Engine</a></li><li><a href="/product/openinfraquote" class="hover:text-accent transition-colors">OpenInfraQuote</a></li><li><a href="/api" class="hover:text-accent transition-colors">API</a></li><li><a href="/product/deployment" class="hover:text-accent transition-colors">Cloud &amp; On-prem</a></li><li><a href="/product/security-and-compliance" class="hover:text-accent transition-colors">Security &amp; Compliance</a></li><li><a href="/technical-architecture" class="hover:text-accent transition-colors">Technical Architecture</a></li><li><a href="/pricing" class="hover:text-accent transition-colors">Pricing</a></li><li><a href="/demo" class="hover:text-accent transition-colors">Demo</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Resources</h4><ul class="space-y-3"><li><a href="/blog" class="hover:text-accent transition-colors">Blog</a></li><li><a href="/community" class="hover:text-accent transition-colors">Community</a></li><li><a href="https://docs.terrateam.io" class="hover:text-accent transition-colors">Docs</a></li><li><a href="/gitops" class="hover:text-accent transition-colors">GitOps</a></li><li><a href="/philosophy" class="hover:text-accent transition-colors">Philosophy</a></li><li><a href="/open-source" class="hover:text-accent transition-colors">Open Source</a></li><li><a href="/support" class="hover:text-accent transition-colors">Support</a></li><li><a href="/status" class="hover:text-accent transition-colors">Status</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Use Cases</h4><ul class="space-y-3"><li><a href="/use-cases/scale-infrastructure" class="hover:text-accent transition-colors">IaC at Scale</a></li><li><a href="/use-cases/infrastructure-governance" class="hover:text-accent transition-colors">Governance &amp; Security</a></li><li><a href="/use-cases/developer-self-service" class="hover:text-accent transition-colors">Developer Self-Service</a></li><li><a href="/use-cases/drift-detection" class="hover:text-accent transition-colors">Drift Detection</a></li><li><a href="/use-cases/cost-optimization" class="hover:text-accent transition-colors">Cost Optimization</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Consulting</h4><ul class="space-y-3"><li><a href="/consulting/terraform-opentofu" class="hover:text-accent transition-colors">Terraform &amp; OpenTofu</a></li><li><a href="/consulting/managed-infrastructure" class="hover:text-accent transition-colors">Managed Infrastructure</a></li><li><a href="/consulting/bare-metal-cloud" class="hover:text-accent transition-colors">Bare-metal to Cloud</a></li><li><a href="/consulting" class="hover:text-accent transition-colors">How We Work</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Company</h4><ul class="space-y-3"><li><a href="/about" class="hover:text-accent transition-colors">About</a></li><li><a href="/contact" class="hover:text-accent transition-colors">Contact</a></li><li><a href="/privacy-policy" class="hover:text-accent transition-colors">Privacy Policy</a></li><li><a href="/terms-of-service" class="hover:text-accent transition-colors">Terms of Service</a></li><li><a href="/security" class="hover:text-accent transition-colors">Security</a></li><li><a href="/careers" class="hover:text-accent transition-colors">Careers</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Compare</h4><ul class="space-y-3"><li><a href="/compare/atlantis" class="hover:text-accent transition-colors">Atlantis</a></li><li><a href="/compare/terraform-cloud" class="hover:text-accent transition-colors">Terraform Cloud</a></li><li><a href="/compare/build-vs-buy" class="hover:text-accent transition-colors">Build vs. Buy</a></li></ul></div><div><h4 class="text-text-primary font-semibold mb-4">Open Source</h4><ul class="space-y-3"><li><a href="https://github.com/terrateamio/terrateam" class="hover:text-accent transition-colors flex items-center group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-text-muted group-hover:text-accent flex-shrink-0"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path><path d="M9 18c-4.51 2-5-2-7-2"></path></svg>Terrateam</a></li><li><a href="https://github.com/terrateamio/openinfraquote" class="hover:text-accent transition-colors flex items-center group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-text-muted group-hover:text-accent flex-shrink-0"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path><path d="M9 18c-4.51 2-5-2-7-2"></path></svg>OpenInfraQuote</a></li><li><a href="https://github.com/terrateamio/terrateam/releases" class="hover:text-accent transition-colors flex items-center group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-text-muted group-hover:text-accent flex-shrink-0"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" x2="8" y1="13" y2="13"></line><line x1="16" x2="8" y1="17" y2="17"></line><line x1="10" x2="8" y1="9" y2="9"></line></svg>Changelog</a></li><li><a href="https://github.com/terrateamio/terrateam/issues" class="hover:text-accent transition-colors flex items-center group"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4 mr-2 text-text-muted group-hover:text-accent flex-shrink-0"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>Issues</a></li></ul></div></div></div><div class="border-t border-theme-border pt-8 mt-8 flex flex-col md:flex-row justify-between items-center"><div class="text-sm text-text-dim mb-4 md:mb-0">© <!-- -->2026<!-- --> Terrateam. All rights reserved.</div><div class="flex space-x-6"><a href="https://github.com/terrateamio/terrateam" class="text-text-muted hover:text-accent transition-colors" target="_blank" rel="noopener noreferrer" aria-label="Visit Terrateam on GitHub"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"></path><path d="M9 18c-4.51 2-5-2-7-2"></path></svg></a><a href="https://twitter.com/terrateamio" class="text-text-muted hover:text-accent transition-colors" target="_blank" rel="noopener noreferrer" aria-label="Follow Terrateam on Twitter"><svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></svg></a><a href="https://linkedin.com/company/terrateamio" class="text-text-muted hover:text-accent transition-colors" target="_blank" rel="noopener noreferrer" aria-label="Connect with Terrateam on LinkedIn"><svg class="h-5 w-5" fill="currentColor" viewBox="0 0 24 24"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path></svg></a><a href="/slack" class="text-text-muted hover:text-accent transition-colors" aria-label="Join Terrateam on Slack"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="h-5 w-5"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg></a></div></div></div></footer><div class="absolute bottom-4 right-4 sm:bottom-6 sm:right-6 z-50 cursor-pointer group touch-manipulation"><div class="relative bg-bg/90 border border-orange-600/60 w-12 h-12 sm:w-11 sm:h-11 flex items-center justify-center transition-all duration-300 hover:border-red-600 active:border-red-600 hover:bg-black active:bg-black hover:shadow-[0_0_15px_rgba(220,38,38,0.5)] active:shadow-[0_0_15px_rgba(220,38,38,0.5)]"><div class="absolute top-0 left-0 w-1.5 h-1.5 border-t border-l border-orange-500/70 group-hover:border-red-500 group-active:border-red-500 transition-colors"></div><div class="absolute top-0 right-0 w-1.5 h-1.5 border-t border-r border-orange-500/70 group-hover:border-red-500 group-active:border-red-500 transition-colors"></div><div class="absolute bottom-0 left-0 w-1.5 h-1.5 border-b border-l border-orange-500/70 group-hover:border-red-500 group-active:border-red-500 transition-colors"></div><div class="absolute bottom-0 right-0 w-1.5 h-1.5 border-b border-r border-orange-500/70 group-hover:border-red-500 group-active:border-red-500 transition-colors"></div><div class="text-3xl sm:text-2xl font-serif text-orange-400/80 group-hover:text-red-400 group-active:text-red-400 transition-colors">π</div></div></div></div></div>
<script id="vike_pageContext" type="application/json">{"pageProps":{"is404":false},"data":{"post":{"slug":"using-llms-to-generate-terraform-code","title":"Using LLMs to Generate Terraform Code - 2025 Update","description":"An in-depth analysis using Claude, ChatGPT, and Mistral","pubDate":"2025-07-28T00:00:00.000Z","tags":["terraform","infrastructure","iac","security","llm","github","open-source"],"authors":["mike-vanbuskirk"],"content":"\u003cp>We originally tested ChatGPT 4, Claude 3 Opus, and Mistral Large over a year ago. The AI landscape has changed significantly, with modern LLM models far eclipsing the previous generation in capabilities. With that in mind, we&#39;ve updated this post with evaluations of the current models, and also briefly discuss some of the most significant changes in AI as they relate to infrastructure as code.\u003c/p>\n\u003cp style=\"background-color: #f5f5f5; border-left: 4px solid #1a73e8; padding: 14px 18px; margin: 20px 0; font-size: 16px;\">\n💡 \u003cem>Looking for help with Terraform? We provide \u003ca href=\"/consulting/terraform-opentofu\">expert consulting services\u003c/a> for infrastructure automation.\u003c/em>\n\u003c/p>\n\n\u003cdiv style=\"background-color: #e8f5e9; border: 1px solid #c8e6c9; border-radius: 8px; padding: 20px; margin: 20px 0;\">\n\u003ch2 style=\"margin-top: 0; color: #333;\">TL;DR\u003c/h2>\n\n\u003cp>We tested four leading LLMs (OpenAI o3, Claude Sonnet 4, Mistral Le Chat Pro, and Google Gemini 2.5 Pro) on generating Terraform configurations for a simple AWS application. \u003c/p>\n\u003cp>\u003cstrong>Winners: Claude Sonnet 4 and Gemini 2.5 Pro (tie)\u003c/strong>\u003c/p>\n\u003cul>\n\u003cli>\u003cstrong>Claude Sonnet 4\u003c/strong>: Excelled with a user-friendly deployment script, single-shot success\u003c/li>\n\u003cli>\u003cstrong>Gemini 2.5 Pro\u003c/strong>: Generated cleanest, best-practice Terraform code structure\u003c/li>\n\u003cli>\u003cstrong>OpenAI o3\u003c/strong>: Succeeded but required 7 iterations to fix various issues\u003c/li>\n\u003cli>\u003cstrong>Mistral Le Chat Pro\u003c/strong>: Disappointed, felt like previous-generation model\u003c/li>\n\u003c/ul>\n\u003cp>\u003cstrong>Key takeaway\u003c/strong>: Modern LLMs are now capable of generating production-ready IaC with proper context and prompting.\u003c/p>\n\u003cp>\u003ca href=\"#2025-findings\">Jump to full findings →\u003c/a>\u003c/p>\n\u003c/div>\n\n\n\u003ch2>2025 Updates\u003c/h2>\n\u003ch3>Rise of Agents/Agentic Workflows\u003c/h3>\n\u003cp>Since the original post was published, agents and agentic AI workflows have moved from bleeding edge to practical application. Cursor and GitHub Copilot both now offer agent workflows, and there are multiple platforms and frameworks for orchestrating multiple agents across a variety of domains. Devin, which we mentioned last year, is now generally available, although it remains to be seen if their fully autonomous approach to agents will gain traction given the current capabilities of LLMs. It looks more likely that the more popular pattern is semi-autonomous agents, with engineers acting as orchestrators/conductors. For DevOps and IaC specifically, Stakpak now offers a dedicated, AI-enabled DevOps IDE with agentic capabilities.\u003c/p>\n\u003ch3>Google Gemini\u003c/h3>\n\u003cp>Virtually a non-entity in the LLM space a year ago, Google has established itself with the launch of its Gemini models, which offer good performance and a staggeringly large context window (Gemini 2.5 Pro offers 2 million tokens). Due to the ubiquity of Gemini 2.5 usage, we&#39;ve decided to include it in our updated evaluations.\u003c/p>\n\u003ch3>Chain of Thought Reasoning\u003c/h3>\n\u003cp>Chain of Thought (CoT) reasoning has become standard across most current-generation language models, allowing them to break down complex problems into logical steps rather than attempting to solve everything in a single response. For infrastructure code generation, this means (in theory) that models should now be able to work through these prompts more systematically and effectively, by breaking the problem down into smaller pieces. We should see some CoT output in the tests, but it will be interesting to see if it leads to better output.\u003c/p>\n\u003ch2>2025 Testing Methodology\u003c/h2>\n\u003cp>We&#39;ll be using the same testing methodology as before, with the same prompt and same hypothetical application infrastructure. The caveats are also the same: evaluating the output of LLMs is ultimately subjective; LLM output is not deterministic. We&#39;ll be doing manual assessment of each model, and will determine if the code generates a &quot;working&quot; application. Any time an error, failure, or other issue is encountered, the model is prompted to fix the issue, and a new iteration begins.\u003c/p>\n\u003ch2>2025 Tests\u003c/h2>\n\u003ch3>Experiment #1: OpenAI - o3\u003c/h3>\n\u003cdetails open>\n\u003csummary>\u003cstrong>View Experiment Details\u003c/strong>\u003c/summary>\n\n\u003ch4>Process\u003c/h4>\n\u003cul>\n\u003cli>A new chat prompt was opened with the o3 model selected.\u003c/li>\n\u003cli>The prompt was entered into the model.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Process Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-1.png\" alt=\"o3 output 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-2.png\" alt=\"o3 output 2\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-3.png\" alt=\"o3 output 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-4.png\" alt=\"o3 output 4\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-5.png\" alt=\"o3 output 5\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-6.png\" alt=\"o3 output 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-7.png\" alt=\"o3 output 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-8.png\" alt=\"o3 output 8\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-9.png\" alt=\"o3 output 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-10.png\" alt=\"o3 output 10\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #1\u003c/h4>\n\u003cul>\n\u003cli>The configurations were placed in their respective files as instructed: versions.tf, variables.tf, main.tf, outputs.tf.\u003c/li>\n\u003cli>We&#39;ve already hit a snag: the instructions ask the user to build and deploy their image before the infrastructure, which includes the ECR registry, is deployed. The model was prompted to correct this.\u003c/li>\n\u003cli>Placeholder values were updated as instructed.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #1 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-11.png\" alt=\"o3 fix 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-12.png\" alt=\"o3 fix 2\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-13.png\" alt=\"o3 fix 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-14.png\" alt=\"o3 fix 4\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #2\u003c/h4>\n\u003cul>\n\u003cli>terraform init was run.\u003c/li>\n\u003cli>Option &quot;A&quot; was chosen from what the model provided, terraform apply was run, targeting the ECR registry only.\u003c/li>\n\u003cli>Terraform reported an error:\u003c/li>\n\u003c/ul>\n\u003cpre>\u003ccode class=\"language-plaintext\">│ Error: Reference to undeclared resource\n│\n│ on main.tf line 106, in module &quot;vpc&quot;:\n│ 106: azs = slice(data.aws_availability_zones.available.names, 0, 2)\n│\n│ A data resource &quot;aws_availability_zones&quot; &quot;available&quot; has not been declared in the root module.\n\u003c/code>\u003c/pre>\n\u003cp>The error message was provided to the model, and the fix was applied.\u003c/p>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #2 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-15.png\" alt=\"o3 fix 5\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #3\u003c/h4>\n\u003cul>\n\u003cli>terraform validate was used to confirm validity of the configuration, which succeeded.\u003c/li>\n\u003cli>The terraform apply -target=aws_ecr_repository.app_repo command was attempted again, and was successful, but issued warnings around the use of targeted terraform apply.\u003c/li>\n\u003cli>The build &amp; push commands were run, however the following error was encountered when attempting to build the image:\u003c/li>\n\u003c/ul>\n\u003cpre>\u003ccode class=\"language-plaintext\">ERROR: failed to build: invalid tag &quot;\\&quot;************.dkr.ecr.us-east-1.amazonaws.com/hello-fargate-picked-sturgeon\\&quot;:latest&quot;: invalid reference format\n\u003c/code>\u003c/pre>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #3 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-16.png\" alt=\"o3 fix 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-17.png\" alt=\"o3 fix 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-18.png\" alt=\"o3 fix 8\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #4\u003c/h4>\n\u003cul>\n\u003cli>Option 2 of the fix was chosen, with a specific output added to outputs.tf\u003c/li>\n\u003cli>terraform apply -refresh-only was run.\u003c/li>\n\u003cli>The new output was set as a Bash variable with: REPO_URL=$(terraform output -raw ecr_repo_url)\u003c/li>\n\u003cli>The build was run again: docker build -t ${REPO_URL}:latest ., and the image was built successfully.\u003c/li>\n\u003cli>The following error was encountered when attempting to authenticate to ECR with: aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPO_URL:\u003c/li>\n\u003c/ul>\n\u003cpre>\u003ccode class=\"language-plaintext\">Provided region_name &#39;╷\n│ Warning: No outputs found\n│\n│ The state file either has no outputs defined, or all the defined outputs are empty. Please define an output in your\n│ configuration with the `output` keyword and run `terraform refresh` for it to become available. If you are using\n│ interpolation, please verify the interpolated value is not empty. You can use the `terraform console` command to assist.\n╵&#39; doesn&#39;t match a supported format.\nError: Cannot perform an interactive login from a non TTY device\n\u003c/code>\u003c/pre>\n\u003cul>\n\u003cli>The model was provided the error, and the fixes were applied.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #4 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-19.png\" alt=\"o3 fix 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-20.png\" alt=\"o3 fix 10\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-21.png\" alt=\"o3 fix 11\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #5\u003c/h4>\n\u003cul>\n\u003cli>aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $REPO_URL was run successfully.\u003c/li>\n\u003cli>docker push ${REPO_URL}:latest was run, and the image was pushed successfully.\u003c/li>\n\u003cli>terraform apply was run, and completed successfully.\u003c/li>\n\u003cli>The app did not run successfully, with a 504 error being generated when viewing the frontend.\u003c/li>\n\u003cli>Upon reviewing the task logs, it was discovered that the DynamoDB table name was not being injected into the container runtime.\u003c/li>\n\u003cli>The model was provided the error, and the fix was applied.\u003c/li>\n\u003c/ul>\n\u003cpre>\u003ccode class=\"language-plaintext\">raise ValueError(&quot;Please set the DYNAMODB_TABLE_NAME environment variable&quot;)\n\u003c/code>\u003c/pre>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #5 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-22.png\" alt=\"o3 fix 12\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-23.png\" alt=\"o3 fix 13\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-24.png\" alt=\"o3 fix 14\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-25.png\" alt=\"o3 fix 15\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #6\u003c/h4>\n\u003cul>\n\u003cli>terraform apply was run.\u003c/li>\n\u003cli>The task successfully started, however when visiting the ALB DNS URL, a Boto3 exception was thrown.\u003c/li>\n\u003cli>The error was provided, and the fix was applied. NOTE: although the model recommends making changes to the application code, in order to maintain as much similarity to the previous test examples, we are implementing option B so that the application differs as little as possible from the previous test runs.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #6 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-26.png\" alt=\"o3 fix 16\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-27.png\" alt=\"o3 fix 17\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-28.png\" alt=\"o3 fix 18\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-29.png\" alt=\"o3 fix 19\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-30.png\" alt=\"o3 fix 20\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-31.png\" alt=\"o3 fix 21\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/o3/o3-32.png\" alt=\"o3 fix 22\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #7\u003c/h4>\n\u003cul>\n\u003cli>terraform apply was run successfully.\u003c/li>\n\u003cli>The endpoint returned &quot;Hello World&quot; successfully.\u003c/li>\n\u003cli>Timestamped entries were confirmed in the DynamoDB Table.\u003c/li>\n\u003c/ul>\n\u003ch4>Notes\u003c/h4>\n\u003cul>\n\u003cli>Compared to the previous generation model, o3 provided much clearer instructions around file structure and where to place configuration blocks. It even made use of a publicly available module.\u003c/li>\n\u003c/ul>\n\u003ch4>Issues\u003c/h4>\n\u003cul>\n\u003cli>The model did not identify the need to first bootstrap the ECR registry before docker images could be pushed and the remaining infrastructure deployed.\u003c/li>\n\u003cli>A data source for availability zones was interpolated before it was created.\u003c/li>\n\u003cli>The docker build command required changes.\u003c/li>\n\u003cli>The command to authenticate to the ECR registry required new outputs to be defined in outputs.tf\u003c/li>\n\u003cli>The environment variable name for the DynamoDB table did not match the application code*\u003c/li>\n\u003cli>The primary key name for the DynamoDB table did not match what was defined in the application code*\u003c/li>\n\u003c/ul>\n\u003ch4>Results\u003c/h4>\n\u003cp>We got a working application! Although it required several iterations, most of the issues stemmed from either the initial bootstrapping and Docker commands, or configuration mismatches with the application code. I&#39;ve marked the last two items with a &quot;*&quot;, as those were not a direct result of model error, rather that the model was not supplied with the application code in its initial prompt and made assumptions.\u003c/p>\n\u003cp>My takeaway is that I am much more impressed with the overall IaC output and capabilities of the model. Compared to the previous OpenAI model, this configuration made much better use of value and variable interpolation, utilized public registry modules, and broke down the configuration into separate .tf files.\u003c/p>\n\u003c/details>\n\n\u003ch3>Experiment #2: Anthropic - Claude Sonnet 4\u003c/h3>\n\u003cdetails open>\n\u003csummary>\u003cstrong>View Experiment Details\u003c/strong>\u003c/summary>\n\n\u003ch4>Process\u003c/h4>\n\u003cul>\n\u003cli>A new chat prompt was opened with the Claude Sonnet 4 model selected.\u003c/li>\n\u003cli>The prompt was entered into the model.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Process Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-1.png\" alt=\"Claude Sonnet 4 output 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-2.png\" alt=\"Claude Sonnet 4 output 2\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-3.png\" alt=\"Claude Sonnet 4 output 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-4.png\" alt=\"Claude Sonnet 4 output 4\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-5.png\" alt=\"Claude Sonnet 4 output 5\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-6.png\" alt=\"Claude Sonnet 4 output 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-7.png\" alt=\"Claude Sonnet 4 output 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-8.png\" alt=\"Claude Sonnet 4 output 8\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-9.png\" alt=\"Claude Sonnet 4 output 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-10.png\" alt=\"Claude Sonnet 4 output 10\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-11.png\" alt=\"Claude Sonnet 4 output 11\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-12.png\" alt=\"Claude Sonnet 4 output 12\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-13.png\" alt=\"Claude Sonnet 4 output 13\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-14.png\" alt=\"Claude Sonnet 4 output 14\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-15.png\" alt=\"Claude Sonnet 4 output 15\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-16.png\" alt=\"Claude Sonnet 4 output 16\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-17.png\" alt=\"Claude Sonnet 4 output 17\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/sonnet-4/sonnet-4-18.png\" alt=\"Claude Sonnet 4 output 18\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #1\u003c/h4>\n\u003cul>\n\u003cli>The model provided explicit instructions for set up, including a deploy.sh script, which was run after the initial directory was set up and files copied over.\u003c/li>\n\u003cli>The deploy script was successfully run, and the app was verified as fully functional.\u003c/li>\n\u003c/ul>\n\u003ch4>Notes\u003c/h4>\n\u003cul>\n\u003cli>Compared to the previous generation Claude model, this output had a much more perceptible focus on user experience; it provided a fully-featured deployment script that addressed the need for bootstrapping the ECR registry, as well as providing the outputs to the user.\u003c/li>\n\u003c/ul>\n\u003ch4>Issues\u003c/h4>\n\u003cul>\n\u003cli>The Terraform configuration was generated entirely within a single file: main.tf. At minimum, most Terraform configurations start with separate files for the resources, variables, outputs, as well as provider and backend configuration.\u003c/li>\n\u003c/ul>\n\u003ch4>Results\u003c/h4>\n\u003cp>Very impressive. The model satisfied the requirements of the prompt in a single shot. The deployment script was a nice touch, and provided easy-to-read outputs, and did a good job of properly bootstrapping the resources to handle building and pushing a Docker image.\u003c/p>\n\u003c/details>\n\n\u003ch3>Experiment #3: Mistral - Le Chat Pro\u003c/h3>\n\u003cdetails open>\n\u003csummary>\u003cstrong>View Experiment Details\u003c/strong>\u003c/summary>\n\n\u003ch4>Process\u003c/h4>\n\u003cul>\n\u003cli>A new chat prompt was opened with the Le Chat Pro model selected.\u003c/li>\n\u003cli>The prompt was entered into the model.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Process Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-1.png\" alt=\"Mistral Le Chat Pro output 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-2.png\" alt=\"Mistral Le Chat Pro output 2\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-3.png\" alt=\"Mistral Le Chat Pro output 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-4.png\" alt=\"Mistral Le Chat Pro output 4\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-5.png\" alt=\"Mistral Le Chat Pro output 5\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-6.png\" alt=\"Mistral Le Chat Pro output 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-7.png\" alt=\"Mistral Le Chat Pro output 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-8.png\" alt=\"Mistral Le Chat Pro output 8\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-9.png\" alt=\"Mistral Le Chat Pro output 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-10.png\" alt=\"Mistral Le Chat Pro output 10\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #1\u003c/h4>\n\u003cul>\n\u003cli>The model provided some basic instructions for setup, including, creating and pushing a Docker image.\u003c/li>\n\u003cli>The model did not correctly interpret the need to have created the ECR registry before pushing the image.\u003c/li>\n\u003cli>The model was prompted with this information, and the fixes were applied.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #1 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-11.png\" alt=\"Mistral Le Chat Pro fix 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-12.png\" alt=\"Mistral Le Chat Pro fix 2\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #2\u003c/h4>\n\u003cul>\n\u003cli>terraform init, terraform plan, and terraform apply were run successfully.\u003c/li>\n\u003cli>The Docker image was built and pushed to the ECR registry.\u003c/li>\n\u003cli>aws ecs update-service --cluster flask-app-cluster --service flask-app-service --force-new-deployment was run successfully.\u003c/li>\n\u003cli>When visiting the endpoint, a 504 error was generated. The model was prompted with this information.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #2 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-13.png\" alt=\"Mistral Le Chat Pro fix 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-14.png\" alt=\"Mistral Le Chat Pro fix 4\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-15.png\" alt=\"Mistral Le Chat Pro fix 5\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #3\u003c/h4>\n\u003cul>\n\u003cli>Since the model provided only generic troubleshooting advice, it was prompted to fix the issue again. At this point, I noticed the model required manually enabling &quot;Think&quot; mode, which was done.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #3 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-16.png\" alt=\"Mistral Le Chat Pro fix 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-17.png\" alt=\"Mistral Le Chat Pro fix 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-18.png\" alt=\"Mistral Le Chat Pro fix 8\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-19.png\" alt=\"Mistral Le Chat Pro fix 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-20.png\" alt=\"Mistral Le Chat Pro fix 10\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-21.png\" alt=\"Mistral Le Chat Pro fix 11\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-22.png\" alt=\"Mistral Le Chat Pro fix 12\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-23.png\" alt=\"Mistral Le Chat Pro fix 13\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #4\u003c/h4>\n\u003cul>\n\u003cli>The new Terraform configuration was copied, and the terraform init, terraform plan, and terraform apply commands were run successfully.\u003c/li>\n\u003cli>When visiting the endpoint, an exception was thrown.\u003c/li>\n\u003cli>The model was prompted with the exception information and asked to fix it.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #4 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-24.png\" alt=\"Mistral Le Chat Pro fix 14\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-25.png\" alt=\"Mistral Le Chat Pro fix 15\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-26.png\" alt=\"Mistral Le Chat Pro fix 16\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #5\u003c/h4>\n\u003cul>\n\u003cli>The model again asked the user to perform generic troubleshooting steps, and was prompted to fix the issue.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #5 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-27.png\" alt=\"Mistral Le Chat Pro fix 17\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-28.png\" alt=\"Mistral Le Chat Pro fix 18\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-29.png\" alt=\"Mistral Le Chat Pro fix 19\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-30.png\" alt=\"Mistral Le Chat Pro fix 20\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-31.png\" alt=\"Mistral Le Chat Pro fix 21\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-32.png\" alt=\"Mistral Le Chat Pro fix 22\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-33.png\" alt=\"Mistral Le Chat Pro fix 23\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-34.png\" alt=\"Mistral Le Chat Pro fix 24\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #6\u003c/h4>\n\u003cul>\n\u003cli>The new Terraform configuration was copied over, and terraform init, plan, apply commands were run.\u003c/li>\n\u003cli>An error was received:\u003c/li>\n\u003c/ul>\n\u003cpre>\u003ccode class=\"language-plaintext\">│ Error: creating IAM Role (ecsTaskExecutionRole): EntityAlreadyExists: Role with name ecsTaskExecutionRole already exists.\n│ status code: 409, request id: 69650f31-7e87-49d5-bddf-10926e57010c\n│\n│ with aws_iam_role.ecs_task_execution_role,\n│ on main.tf line 52, in resource &quot;aws_iam_role&quot; &quot;ecs_task_execution_role&quot;:\n│ 52: resource &quot;aws_iam_role&quot; &quot;ecs_task_execution_role&quot; {\n│\n\u003c/code>\u003c/pre>\n\u003cul>\n\u003cli>On further investigation, it was also discovered the Terraform configuration contained the same error that had plagued the previous generation models: it did not create separate execution and task roles.\u003c/li>\n\u003cli>The model was prompted with this information. (NOTE: after generating a new config and instructions, the model generated a large amount of repeating text.)\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Iteration #6 Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-35.png\" alt=\"Mistral Le Chat Pro fix 25\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/le-chat-pro/lechat-36.png\" alt=\"Mistral Le Chat Pro fix 26\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #7\u003c/h4>\n\u003cul>\n\u003cli>The new Terraform configuration was copied over, and terraform init, plan, apply commands were run successfully.\u003c/li>\n\u003cli>aws ecs update-service --cluster flask-app-cluster --service flask-app-service --force-new-deployment was run to ensure the latest task definition was being used.\u003c/li>\n\u003cli>The endpoint successfully returned &quot;Hello World&quot;, with entries written to the DynamoDB table.\u003c/li>\n\u003c/ul>\n\u003ch4>Notes\u003c/h4>\n\u003cul>\n\u003cli>Unfortunately, this felt like I was still interacting with a previous-generation LLM model. It frequently asked the user to perform generic troubleshooting steps rather than fixing its own work, and made several errors.\u003c/li>\n\u003c/ul>\n\u003ch4>Issues\u003c/h4>\n\u003cul>\n\u003cli>The model frequently defaulted to asking the user to perform generic troubleshooting steps.\u003c/li>\n\u003cli>The model did not correctly interpret that the ECR registry would need to be created before a Docker image could be pushed.\u003c/li>\n\u003cli>The need for separate task and execution roles was not properly addressed until specifically called out by the user.\u003c/li>\n\u003cli>A configuration was generated that would not even complete a terraform apply without failure.\u003c/li>\n\u003cli>A single Terraform file was generated, rather than multiple files.\u003c/li>\n\u003cli>The model asked the user to perform several manual commands, rather than attempting to fulfill the requirement that the user should have only minimal intervention.\u003c/li>\n\u003c/ul>\n\u003ch4>Results\u003c/h4>\n\u003cp>Even with &quot;Thinking&quot; mode turned on, the Le Chat model very much gave the impression that I was still interacting with a previous generation of LLM. The issues and rough edges I encountered were all very typical for the models that were tested over a year ago. Eventually we did converge on a working application, but it felt like a lot of work to arrive at that point.\u003c/p>\n\u003c/details>\n\n\u003ch3>Experiment #4: Google - Gemini 2.5 Pro\u003c/h3>\n\u003cdetails open>\n\u003csummary>\u003cstrong>View Experiment Details\u003c/strong>\u003c/summary>\n\n\u003ch4>Process\u003c/h4>\n\u003cul>\n\u003cli>A new chat prompt was opened with the Gemini 2.5 Pro model selected.\u003c/li>\n\u003cli>The prompt was entered into the model.\u003c/li>\n\u003c/ul>\n\u003cdetails>\n\u003csummary>\u003cstrong>View Process Screenshots\u003c/strong>\u003c/summary>\n\n\u003cp>\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-1.png\" alt=\"Gemini 2.5 Pro output 1\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-2.png\" alt=\"Gemini 2.5 Pro output 2\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-3.png\" alt=\"Gemini 2.5 Pro output 3\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-4.png\" alt=\"Gemini 2.5 Pro output 4\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-5.png\" alt=\"Gemini 2.5 Pro output 5\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-6.png\" alt=\"Gemini 2.5 Pro output 6\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-7.png\" alt=\"Gemini 2.5 Pro output 7\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-8.png\" alt=\"Gemini 2.5 Pro output 8\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-9.png\" alt=\"Gemini 2.5 Pro output 9\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-10.png\" alt=\"Gemini 2.5 Pro output 10\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-11.png\" alt=\"Gemini 2.5 Pro output 11\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-12.png\" alt=\"Gemini 2.5 Pro output 12\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-13.png\" alt=\"Gemini 2.5 Pro output 13\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-14.png\" alt=\"Gemini 2.5 Pro output 14\">\n\u003cimg src=\"/blog/using-llms-to-generate-terraform-code/Terraform%20and%20LLM%20Article%202025%20Update%20-%20Images/gemini-25/gemini-15.png\" alt=\"Gemini 2.5 Pro output 15\">\u003c/p>\n\u003c/details>\n\n\u003ch4>Iteration #1\u003c/h4>\n\u003cul>\n\u003cli>The Terraform configurations were copied to their respective files.\u003c/li>\n\u003cli>terraform init and terraform apply -auto-approve were run per model instructions.\u003c/li>\n\u003cli>The commands to build and push the Docker image were run successfully.\u003c/li>\n\u003cli>The outputs were added to the outputs.tf file.\u003c/li>\n\u003cli>Per instructions, terraform apply -auto-approve was run successfully.\u003c/li>\n\u003cli>The ecs service was updated via aws ecs update-service --cluster $(terraform output -raw ecs_cluster_name) --service $(terraform output -raw ecs_service_name) --force-new-deployment --region\u003c/li>\n\u003cli>The app successfully returned &quot;Hello World&quot;, and the DynamoDB table was populated with items.\u003c/li>\n\u003c/ul>\n\u003ch4>Notes\u003c/h4>\n\u003cul>\n\u003cli>This is the first time testing the Gemini 2.5 model.\u003c/li>\n\u003c/ul>\n\u003ch4>Issues\u003c/h4>\n\u003cul>\n\u003cli>This is more of a nit, but there was more manual work for the user compared to the Claude Sonnet 4 model, which bundled all commands in a deployment script.\u003c/li>\n\u003c/ul>\n\u003ch4>Results\u003c/h4>\n\u003cp>The Gemini 2.5 model jumps out of the gate with a great showing, managing to produce a working configuration in one pass. It also produced the cleanest output, breaking down Terraform configuration into multiple files that were easy to access via the chat UI. The Terraform configuration also made use of variables and interpolation as well; very impressive.\u003c/p>\n\u003c/details>\n\n\u003ch2>2025 Findings\u003c/h2>\n\u003cp>Compared to the 2024 results, these models have significantly improved when it comes to generating valid, working IaC configurations. Three out of the four models seem to have largely eliminated the problems that plagued the earlier generations and converged on a working solution with much less user intervention required.\u003c/p>\n\u003cp>Picking a winner is tough; it&#39;s basically a tie between Claude Sonnet 4 and Google Gemini 2.5 Pro. The Sonnet 4 model generated an end-to-end deployment script that required very little work on the part of the user to arrive at a working solution. However, the Gemini model generated Terraform configurations that were much closer to canonical best practice (multiple files). Compared to these two, the Mistral Le Chat Pro model was a disappointment. It eventually produced a working configuration, but it really felt like interacting with a previous generation model. It made the same mistakes as the previous models, and it required far more work on the part of the user to produce a working solution.\u003c/p>\n\u003cp>Compared to last year, I think the takeaway is that we are much closer to being able to depend on LLMs to generate full, possibly production ready IaC configurations. While these tests were still based on a very simple infrastructure abstraction, we also must consider that our prompt provided a bare minimum of context, and the explicit goal was to arrive at a working solution with as little user input as possible, not necessarily to generate a scalable, enterprise-ready configuration. With what we now know about prompting and context, it&#39;s much more likely that an engineer could deploy a model within an engineering team, provide it the necessary prompts and context (like existing code samples), and it would be capable of generating production-ready configurations.\u003c/p>\n\u003cscript>\n// Add progressive enhancement for better UX\ndocument.addEventListener('DOMContentLoaded', function() {\n // Store the state of details elements in sessionStorage\n const detailsElements = document.querySelectorAll('details');\n \n detailsElements.forEach((details, index) => {\n const key = `llm-terraform-details-${index}`;\n \n // Check if we have a stored state\n const storedState = sessionStorage.getItem(key);\n if (storedState !== null) {\n details.open = storedState === 'true';\n }\n \n // Store state when toggled\n details.addEventListener('toggle', function() {\n sessionStorage.setItem(key, details.open);\n });\n });\n \n // Add expand/collapse all functionality\n const article = document.querySelector('article');\n if (article) {\n const controlsDiv = document.createElement('div');\n controlsDiv.style.cssText = 'margin: 20px 0; text-align: right;';\n \n const expandAllBtn = document.createElement('button');\n expandAllBtn.textContent = 'Expand All Sections';\n expandAllBtn.style.cssText = 'margin-right: 10px; padding: 8px 16px; background: #1a73e8; color: white; border: none; border-radius: 4px; cursor: pointer;';\n \n const collapseAllBtn = document.createElement('button');\n collapseAllBtn.textContent = 'Collapse All Sections';\n collapseAllBtn.style.cssText = 'padding: 8px 16px; background: #666; color: white; border: none; border-radius: 4px; cursor: pointer;';\n \n expandAllBtn.addEventListener('click', function() {\n detailsElements.forEach(details => {\n details.open = true;\n });\n });\n \n collapseAllBtn.addEventListener('click', function() {\n detailsElements.forEach(details => {\n details.open = false;\n });\n });\n \n controlsDiv.appendChild(expandAllBtn);\n controlsDiv.appendChild(collapseAllBtn);\n \n // Insert controls after the TL;DR section\n const tldrSection = article.querySelector('div[style*=\"background-color: #e8f5e9\"]');\n if (tldrSection && tldrSection.nextSibling) {\n tldrSection.parentNode.insertBefore(controlsDiv, tldrSection.nextSibling);\n }\n }\n});\n\u003c/script>\n"}},"urlPathname":"/blog/using-llms-to-generate-terraform-code","_urlRewrite":null,"pageId":"/pages/blog/@slug","routeParams":{"slug":"using-llms-to-generate-terraform-code"}}</script>
<script id="vike_globalContext" type="application/json">{}</script>
<script src="/assets/entries/entry-server-routing.DRXQ4ZAn.js" type="module" async></script>
<link rel="modulepreload" href="/assets/entries/pages_blog_-slug.CD2myAfS.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-hePW80VL.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-C5Xo0Kq5.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-CrbWWvBX.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-o18ScuGs.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-BGZw7rwg.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-B_XnCu77.js" as="script" type="text/javascript">
<link rel="modulepreload" href="/assets/chunks/chunk-Czpn1I53.js" as="script" type="text/javascript">
</body>
</html>