How to Build a Production-Ready Auto-Scaling Azure Web App with Modular Terraform (VMSS, Load Balancer & NAT Gateway)

7 min read

From Basic Terraform to Production IaC: Building an Auto-Scaling Azure Web App with Modular Terraform.

Many engineers begin learning Terraform by placing everything inside a single main.tf file. This approach works well for understanding syntax and basic resource creation. However, as soon as infrastructure grows beyond a few resources, single-file Terraform projects become difficult to maintain, risky to change, and nearly impossible to scale safely.

Production environments demand far more than working code. They require clarity, reusability, governance, and predictable behavior during change. This is where the real transition happens, moving from learning Terraform to engineering with Terraform.

In this hands-on project tutorial, I moved beyond basic resource definitions and focused on designing modular, production-ready Infrastructure as Code (IaC). The goal was to reflect how Cloud Engineers, DevOps Engineers, and SRE teams actually design and operate scalable, resilient Azure platforms in real environments.

If you’re still early in your Azure journey, you may find it helpful to first review Setting Up Clean Azure VNets, Subnets & Tagging, which explains the network and governance foundations used throughout this lab.

Architecture Overview: What We’re Building

At the core of this project is a fully automated, auto-scaling Azure web application, deployed end-to-end using modular Terraform.

Rather than focusing on a single Azure service, this lab demonstrates how multiple infrastructure layers work together to deliver scalability, security, and reliability.

Core Architecture Components

The solution includes:

  • Azure Virtual Network (VNet) providing network isolation

  • Dedicated subnets separating compute resources from other network layers

  • Network Security Groups (NSGs) enforcing least-privilege inbound and outbound access

  • NAT Gateway ensuring secure and predictable outbound internet connectivity

  • Standard Azure Load Balancer distributing inbound traffic

  • Azure VM Scale Set (Flexible orchestration mode) enabling horizontal scaling and fault tolerance

  • PHP web application, bootstrapped automatically on each VM using cloud-init

Design decisions emphasize fault tolerance, horizontal scalability, and clear separation of concerns. Each layer has a single responsibility, reducing blast radius and simplifying troubleshooting.

For a deeper explanation of how Azure networking is designed and validated in production, see Azure Networking with PowerShell: VNet Design, Peering, VM Provisioning & Network Watcher.

Why Modular Terraform Matters in Production

Terraform modules are not about splitting files; they are about isolating responsibility.

In real environments:

  • Different teams often own different layers (networking, security, compute)

  • Changes must be scoped and predictable

  • Reuse across environments (dev, test, prod) is essential

By designing with modules, you create guardrails, not just code.

This approach aligns naturally with Azure governance best practices, including consistent tagging, naming standards, and controlled blast radius. If governance is new to you, review Azure Policy, Tags, and Resource Locks Explained: A Complete Governance Guide for Cloud Engineers before expanding this lab further.

Project Structure: Modular Terraform Layout

Rather than placing all resources into one file, the infrastructure is organized into purpose-built Terraform modules, each responsible for a single layer of the system.

High-Level Structure

  • modules/network – networking and outbound connectivity

  • modules/security – network security and governance controls

  • modules/loadbalancer – traffic distribution and health checks

  • modules/compute – VM Scale Set and auto-scaling logic

  • environments/prod – environment-specific configuration and orchestration

Each module exists to encapsulate responsibility, not just to group files. This approach allows teams to change one part of the system without unintentionally impacting others.

Each module exists to solve a specific problem, not just to group files.

Module Responsibilities

  • Network module
    Owns VNet creation, subnet design, routing, and outbound connectivity (including NAT Gateway)

  • Security module
    Enforces NSGs, least-privilege rules, and governance-aligned access controls

  • Load balancer module
    Handles inbound traffic distribution, health probes, and backend pool association

  • Compute module
    Manages the VM Scale Set, auto-scaling rules, and cloud-init bootstrapping

  • Environment layer
    Wires modules together and applies environment-specific configuration

This structure makes the codebase safer to change, easier to reason about, and reusable across multiple environments.

This structure makes the codebase easier to reason about, safer to change, and reusable across environments.

🎥 Video Walkthrough

What I Demonstrated in the Video

This project tutorial is fully broken down in the accompanying video walkthrough.

Auto-Scaling Compute with Azure VM Scale Sets

The application layer is built using Azure VM Scale Sets (flexible mode).

Why Flexible Mode?

Flexible orchestration provides:

  • Zone awareness

  • Better fault isolation

  • Greater control over instance behavior

  • Compatibility with Standard Load Balancer

Each VM instance is bootstrapped automatically using cloud-init a script, which installs the PHP runtime and application dependencies during provisioning. This ensures consistent, repeatable builds without manual intervention.

For teams that want even stronger consistency guarantees, combining VMSS with custom images is common. See Building Golden Images with Azure Compute Gallery: Custom VM Image Creation & Deployment for a deeper dive.

Traffic Flow and Load Balancing

Inbound traffic is handled by a Standard Azure Load Balancer, configured with:

  • Frontend IP configuration

  • Backend address pool (VMSS instances)

  • Health probes to detect unhealthy nodes

  • Load-balancing rules for HTTP traffic

The load balancer distributes traffic evenly across healthy VM instances, while auto-scaling policies ensure capacity grows and shrinks based on demand.

This model mirrors the same traffic patterns used in many production Azure web platforms.

Secure and Predictable Networking

Security and networking are treated as first-class citizens, not afterthoughts.

Key Networking Principles Applied

  • Subnet isolation prevents accidental exposure

  • NSGs enforce least-privilege rules, limiting access to required ports only

  • NAT Gateway ensures predictable outbound IP addresses, which is critical for:

    • External API allow-listing

    • Security monitoring

    • Compliance requirements

This approach aligns with best practices used across enterprise Azure environments.

If you want to explore secure infrastructure patterns using declarative templates, review Build a Secure Azure Environment in Minutes with Bicep: VMs, Networking, Private Endpoints & Blob Replication.

Terraform Best Practices Applied

Several production-grade Terraform practices are used throughout the project:

  • Modular structure for scalability and reuse

  • Variables and locals to enforce DRY patterns

  • Variable validation to prevent invalid inputs

  • Version pinning for Terraform and providers to ensure stability

  • Remote backend using Azure Blob Storage for shared state management

  • Consistent naming and tagging for governance and cost tracking

Remote state is essential for collaboration and safety. For a deeper look at Azure storage security in this context, see Securing Azure Blob Storage with PowerShell: Network Isolation, SAS Access & Immutable Policies.

Observability and Validation

Once deployed, infrastructure should not be trusted blindly.

Scaling behavior and availability can be validated directly in the Azure Portal, while metrics and alerts provide ongoing visibility.

To take this further in real environments, integrate monitoring using How to Set Up Azure Monitor Alerts, Action Groups, and Processing Rules (Step-by-Step Guide) so scaling and availability issues are detected automatically.

Source Code and Repository

The complete Terraform configuration used in this lab is available on GitHub.

💡 Tip: Clone the repository before starting the lab so you can follow along step by step and experiment safely in your own Azure subscription.

👉 GitHub Repository
https://github.com/sirhumble07/azure-vmss-load-balanced-scalable-webapp-terraform

Repository Includes

  • Modular Terraform code (network, security, load balancing, compute)

  • VM Scale Set configuration with auto-scaling

  • cloud-init scripts for application bootstrapping

  • Azure Blob Storage remote backend configuration

  • Environment-specific variables and outputs

Cloning the repository and reviewing it alongside this tutorial will help you understand how production Terraform projects are structured in practice.

Deployment Workflow

Deployment follows the standard Terraform lifecycle:

  1. terraform init
    Initializes providers and configures the remote backend

  2. terraform plan
    Previews changes before anything is applied

  3. terraform apply
    Provisions the full environment

After deployment, scaling behavior can be tested under load and validated through the Azure Portal and metrics dashboards.

Cleanup and Cost Control

Labs should always be designed with teardown in mind.

Safe Teardown

terraform destroy

This cleanly removes all managed resources, ensuring no orphaned infrastructure remains.

Cost Governance Mindset

Destroying unused environments reinforces cost awareness, an essential habit in professional cloud engineering. Technical excellence includes both engineering correctness and financial responsibility.

Final Thoughts

This project represents a shift from basic Terraform usage to production-ready Infrastructure as Code. By applying modular design, governance principles, and real Azure architecture patterns, you build systems that scale safely and evolve predictably.

If you’re serious about cloud engineering, this is the level of thinking that moves you from lab builder to platform engineer.


Discover more from Humble Cloud Tech

Subscribe to get the latest posts sent to your email.

Leave a Comment

Your email address will not be published. Required fields are marked *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. View more
Cookies settings
Accept
Decline
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active

Who we are

Suggested text: Our website address is: https://humbletech.cloud.

Comments

Suggested text: When visitors leave comments on the site we collect the data shown in the comments form, and also the visitor’s IP address and browser user agent string to help spam detection. An anonymised string created from your email address (also called a hash) may be provided to the Gravatar service to see if you are using it. The Gravatar service Privacy Policy is available here: https://automattic.com/privacy/. After approval of your comment, your profile picture is visible to the public in the context of your comment.

Media

Suggested text: If you upload images to the website, you should avoid uploading images with embedded location data (EXIF GPS) included. Visitors to the website can download and extract any location data from images on the website.

Cookies

Suggested text: If you leave a comment on our site you may opt in to saving your name, email address and website in cookies. These are for your convenience so that you do not have to fill in your details again when you leave another comment. These cookies will last for one year. If you visit our login page, we will set a temporary cookie to determine if your browser accepts cookies. This cookie contains no personal data and is discarded when you close your browser. When you log in, we will also set up several cookies to save your login information and your screen display choices. Login cookies last for two days, and screen options cookies last for a year. If you select "Remember Me", your login will persist for two weeks. If you log out of your account, the login cookies will be removed. If you edit or publish an article, an additional cookie will be saved in your browser. This cookie includes no personal data and simply indicates the post ID of the article you just edited. It expires after 1 day.

Embedded content from other websites

Suggested text: Articles on this site may include embedded content (e.g. videos, images, articles, etc.). Embedded content from other websites behaves in the exact same way as if the visitor has visited the other website. These websites may collect data about you, use cookies, embed additional third-party tracking, and monitor your interaction with that embedded content, including tracking your interaction with the embedded content if you have an account and are logged in to that website.

Who we share your data with

Suggested text: If you request a password reset, your IP address will be included in the reset email.

How long we retain your data

Suggested text: If you leave a comment, the comment and its metadata are retained indefinitely. This is so we can recognise and approve any follow-up comments automatically instead of holding them in a moderation queue. For users that register on our website (if any), we also store the personal information they provide in their user profile. All users can see, edit, or delete their personal information at any time (except they cannot change their username). Website administrators can also see and edit that information.

What rights you have over your data

Suggested text: If you have an account on this site, or have left comments, you can request to receive an exported file of the personal data we hold about you, including any data you have provided to us. You can also request that we erase any personal data we hold about you. This does not include any data we are obliged to keep for administrative, legal, or security purposes.

Where your data is sent

Suggested text: Visitor comments may be checked through an automated spam detection service.
Save settings
Scroll to Top