Deploy a Python API to Azure with IaC

Deploy a Flask API to Azure App Service using Bicep Infrastructure as Code.

Introduction

30 Second Summary

Every government agency and enterprise company needs its applications running reliably in the cloud. Deploying an app manually is one thing, but defining your entire infrastructure in a file that anyone can review, repeat, and audit is what separates a cloud professional from someone who just clicks buttons.

In this project, you will build a Python API and deploy it live to Azure using both the command line and Infrastructure as Code. By the end, you'll have a working app on the internet and a repeatable template that defines your cloud resources declaratively.

What You'll Build

A Python Flask REST API deployed to Azure App Service using a Bicep template that defines your infrastructure as code.

By the end of this project, you'll have:

  • A Python Flask API with multiple endpoints returning real data, running live on the internet.
  • An Azure App Service hosting your application on the free tier, deployed using the Azure CLI.
  • A Bicep template that defines your entire cloud infrastructure in a single file, deployable with one command.
  • Secret Mission: Add a health check endpoint and configure live log streaming to monitor your API in real time.

Are there any prerequisites?

No prior cloud experience is needed. This project walks you through installing every tool from scratch, including Python, the Azure CLI, and VS Code extensions.

Install Python and Azure CLI

To deploy your Python API to Azure, you need three tools installed on your machine.

In this step, you'll install Python 3.13 (the language your API runs on), the Azure CLI (your command-line interface to Azure's cloud), and the Bicep extension for VS Code (for writing infrastructure code later).

In this step, get ready to:
  • Install Python 3.13.
  • Install the Azure CLI.
  • Install the Bicep VS Code extension.
Install Python 3.13

Python is the language your Flask API is written in. Azure App Service needs Python 3.13 specifically, so you need that exact version on your machine.

  • Open your terminal by pressing Cmd+Space to open Spotlight, typing Terminal, and pressing Enter.
  • Check your current Python version by running this command:
python3 --version

Look at the output and pick the tab that matches what you see.

✔️ I see version 3.13

Python 3.13 is ready. Move on to the next substep.

ⓧ I see an older version

Your Mac has an older version of Python installed. On macOS, the system Python is often 3.9 or 3.12, which won't work for this project. You need to install Python 3.13 alongside it using Homebrew.

  • Install Python 3.13 by running this command:
brew install python@3.13

Why python3.13 instead of python3?

When you install a versioned Python formula via Homebrew, it creates a python3.13 binary but does not override your existing python3 symlink. This means python3 --version may still show the old version.

Throughout this project, use python3.13 whenever you need to invoke Python directly.

  • Verify your new installation by running:
python3.13 --version

You should see a version number starting with Python 3.13.

Homebrew not found?

If you see command not found: brew, you need to install Homebrew first. Visit https://brew.sh and follow the one-line install command on the homepage.

help me install Homebrew on my Mac

ⓧ Command not found

Python isn't installed yet. You'll install it using Homebrew, the macOS package manager.

  • Install Python 3.13 by running this command:
brew install python@3.13
  • Verify the installation by running:
python3.13 --version

You should see a version number starting with Python 3.13.

Using python3.13 throughout this project

When you install a versioned Python formula via Homebrew, it creates a python3.13 binary. Throughout this project, use python3.13 whenever you need to invoke Python directly.

Homebrew not found?

If you see command not found: brew, you need to install Homebrew first. Visit https://brew.sh and follow the one-line install command on the homepage.

help me install Homebrew on my Mac

Install the Azure CLI

The Azure CLI lets you create, manage, and delete Azure resources directly from your terminal. You'll use it to deploy your API and manage your cloud infrastructure.

  • Check if the Azure CLI is already installed by running:
az version

Pick the tab that matches what you see.

✔️ I see a version number

The Azure CLI is installed and ready. Move on to the next substep.

ⓧ Command not found

The Azure CLI isn't installed yet. You'll install it using Homebrew.

  • Install the Azure CLI by running these commands:
brew update && brew install azure-cli

This may take a minute or two. Homebrew will download and install the Azure CLI package.

  • Verify the installation by running:
az version

You should see version information printed in your terminal, including a line showing the azure-cli version number.

Install failed or taking too long?

Make sure you have a stable internet connection. If the install hangs, try cancelling with Ctrl+C and running brew update && brew install azure-cli again.

help me troubleshoot my Azure CLI installation on macOS

Install the Bicep VS Code extension

Bicep is Azure's language for defining cloud infrastructure as code. The VS Code extension gives you syntax highlighting, autocompletion, and error checking when writing Bicep templates.

  • Switch to VS Code.
  • Open the Extensions view by pressing Cmd+Shift+X.
  • Type Bicep in the search bar at the top.
  • Find the extension called Bicep published by Microsoft.
  • Click Install.

After a few seconds, you should see the Install button change to a gear icon, confirming the extension is active.

Don't see the extension?

Make sure you're searching for exactly Bicep (not "Azure Bicep" or "Bicep Tasks"). The correct result shows Microsoft as the publisher and describes itself as "Bicep language support for Visual Studio Code".

help me find and install the Bicep extension in VS Code

Your development tools are ready. Next up, you'll create your free Azure account and log in from the command line.

Create Your Azure Account and Log In

Your tools are installed, but they need somewhere to deploy to. Azure is Microsoft's cloud platform, and it's where your Flask API will live once it's accessible to the world.

In this step, you'll create a free Azure account, connect your terminal to it, and verify the connection works. This gives the Azure CLI permission to create and manage cloud resources on your behalf.

In this step, get ready to:
  • Create an Azure free account with $200 credit.
  • Log in to Azure from your terminal.
  • Verify your subscription is active.
Sign up for an Azure free account

Azure offers a free tier that includes $200 in credit for your first 30 days, plus services that remain free indefinitely. You won't be charged for anything in this project.

  • Open the Azure signup page: azure.microsoft.com/en-us/pricing/purchase-options/azure-account
  • Click Try Azure for free.
  • Sign in with your Microsoft account or GitHub account. If you don't have either, the signup flow will help you create one.
  • Enter your phone number for verification.
  • Enter a credit or debit card for identity verification. You will not be charged.
  • Accept the agreement and click Sign up.

Why do I need a credit card?

Azure uses the card only to verify your identity. You may see a temporary $1 authorization that gets reversed immediately. The App Service F1 tier you'll use in this project is permanently free, so nothing gets billed.

Once the signup completes, you'll land on the Azure Portal welcome page. You're ready to connect your terminal.

Log in via the Azure CLI

The Azure CLI needs to know which account to use when creating resources. The az login command opens your browser so you can authenticate.

  • Log in to Azure from your terminal by running this command:
az login

What happens when you run this?

Your default browser opens to a Microsoft login page. Sign in with the same account you just used to create your Azure free account. Once authenticated, the browser shows a success message and your terminal displays your subscription details.

  • Sign in with the same Microsoft or GitHub account you used during signup.
  • Return to your terminal after the browser shows a success message.

Browser didn't open?

If no browser window appears, your terminal may have printed a URL and a code. Copy that URL into your browser manually and enter the code when prompted.

help me troubleshoot why az login isn't opening my browser

Verify your subscription is active

A quick check confirms your terminal is properly connected to your Azure account.

  • Verify your subscription is active by running this command:
az account show

What should I see?

The output is a JSON object with details about your active subscription. Look for the state field showing Enabled and a name field showing your subscription name (often "Azure subscription 1" for free accounts).

You'll also see an id field (your subscription ID) and a tenantId field. These are identifiers, not secrets.

Seeing "Please run 'az login'"?

This means your login session didn't save correctly. Run az login again and make sure you complete the browser authentication before switching back to your terminal.

help me fix the az account show error after logging in to Azure CLI

Your Azure account is live and your terminal is connected. Next up, you'll write the Python Flask API that will run on Azure.

Build Your Python Flask API

Your Azure account is active and ready to host applications. Before you can deploy anything to the cloud, you need an application to deploy.

In this step, you'll build a Python REST API using Flask that serves information about Washington state agencies. Once you verify it works locally, you'll be ready to push it live to Azure.

In this step, get ready to:
  • Create a project directory with a Python virtual environment and install Flask.
  • Write an API with routes that return WA state agency data.
  • Test the API locally to confirm it works before deploying.
Set up your project directory and install Flask

Every Python project should live in its own folder with its own virtual environment. This keeps your project's packages isolated from other projects on your machine.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir wa-agency-api
cd wa-agency-api
  • Confirm the folder exists by running:
ls ~/Desktop

You should see wa-agency-api in the output.

  • Create a virtual environment and activate it by running these commands:
python3 -m venv venv
source venv/bin/activate

What is a virtual environment?

A virtual environment is an isolated Python installation inside your project folder. Packages you install here stay separate from your system Python, so different projects can use different package versions without conflicts.

You'll know it's active when you see (venv) at the start of your terminal prompt.

  • Install Flask by running:
pip install Flask==3.1.3

You should see output ending with a line like Successfully installed Flask-3.1.3 along with its dependencies.

Seeing a permission error or command not found?

  • Make sure your virtual environment is active. You should see (venv) at the start of your terminal prompt.
  • If pip is not found, try pip3 instead.

Still stuck? Help me fix a pip install error in my virtual environment.

  • Create your requirements.txt file to pin your dependency by running:
echo "Flask==3.1.3" > requirements.txt

Why pin the Flask version?

A requirements.txt file records the exact packages your project needs. When you deploy to Azure, the server reads this file to install the same versions you used locally. Without it, your app might break from unexpected package updates.

Write the Flask API

Now you'll write the actual API code. The app will have three endpoints that return data about Washington state agencies as JSON.

  • Open your project folder in VS Code by clicking File in the top menu bar.
  • Click Open Folder.
  • Select the wa-agency-api folder on your Desktop, then click Open.
  • Create a new file called app.py by clicking the new file icon in the Explorer sidebar.

First, you'll set up the app instance and define the agency data it serves.

  • Add the following code to app.py:
from flask import Flask, jsonify

app = Flask(__name__)

agencies = [
    {"id": 1, "name": "Department of Enterprise Services", "abbreviation": "DES", "focus": "Technology and business services"},
    {"id": 2, "name": "Washington Technology Solutions", "abbreviation": "WaTech", "focus": "Cloud and infrastructure services"},
    {"id": 3, "name": "Department of Children, Youth, and Families", "abbreviation": "DCYF", "focus": "Child welfare and family support"},
]

What does this code do?

  • from flask import Flask, jsonify imports the Flask class (to create your app) and jsonify (to send JSON responses).
  • app = Flask(__name__) creates your Flask application instance.
  • agencies is a list of dictionaries, each representing a WA state agency with an ID, name, abbreviation, and focus area.

Next, you'll add the route handlers that define what each URL endpoint returns.

  • Add the following code below the agencies list in app.py:

@app.route("/")
def home():
    return jsonify({"message": "WA State Agency API", "version": "1.0"})


@app.route("/agencies")
def get_agencies():
    return jsonify(agencies)


@app.route("/agencies/<int:agency_id>")
def get_agency(agency_id):
    agency = next((a for a in agencies if a["id"] == agency_id), None)
    if agency is None:
        return jsonify({"error": "Agency not found"}), 404
    return jsonify(agency)

What do these routes do?

  • The / route is the homepage. It returns a welcome message confirming the API is running.
  • The /agencies route returns the full list of agencies as JSON.
  • The /agencies/<int:agency_id> route looks up a single agency by its ID. If the ID doesn't match any agency, it returns a 404 error.
  • Save app.py by pressing Cmd+S (macOS) or Ctrl+S (Windows).

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete app.py file for comparison:

from flask import Flask, jsonify

app = Flask(__name__)

agencies = [
    {"id": 1, "name": "Department of Enterprise Services", "abbreviation": "DES", "focus": "Technology and business services"},
    {"id": 2, "name": "Washington Technology Solutions", "abbreviation": "WaTech", "focus": "Cloud and infrastructure services"},
    {"id": 3, "name": "Department of Children, Youth, and Families", "abbreviation": "DCYF", "focus": "Child welfare and family support"},
]


@app.route("/")
def home():
    return jsonify({"message": "WA State Agency API", "version": "1.0"})


@app.route("/agencies")
def get_agencies():
    return jsonify(agencies)


@app.route("/agencies/<int:agency_id>")
def get_agency(agency_id):
    agency = next((a for a in agencies if a["id"] == agency_id), None)
    if agency is None:
        return jsonify({"error": "Agency not found"}), 404
    return jsonify(agency)

Seeing red squiggly lines in VS Code?

  • VS Code might not be using your virtual environment's Python interpreter. Click the Python version in the bottom status bar, then select the interpreter inside your venv folder.
  • Make sure from flask import Flask, jsonify is the very first line of the file with no extra spaces before it.

Need more help? Help me fix Flask import errors in VS Code.

Test the API locally

Before deploying to Azure, you want to confirm the API works on your machine. Flask includes a built-in development server for exactly this.

  • Switch back to your terminal (make sure you're still in the wa-agency-api folder with (venv) active).
  • Start the Flask development server by running:
flask run

You should see output indicating the server is running at http://127.0.0.1:5000.

  • Open your browser and visit http://127.0.0.1:5000.

You should see a JSON response: {"message":"WA State Agency API","version":"1.0"}.

  • Try the agencies endpoint by visiting http://127.0.0.1:5000/agencies in your browser.
  • Try a single agency lookup by visiting http://127.0.0.1:5000/agencies/1.
  • Stop the server by pressing Ctrl+C in your terminal.

Not seeing JSON in your browser?

  • Make sure the server is still running. If you see an error in the terminal, check that app.py is saved and has no syntax errors.
  • Confirm you are visiting http://127.0.0.1:5000 (not https). Flask's dev server does not use HTTPS.
  • If you see "Address already in use", another process is using port 5000. Stop it or run flask run --port 5001 instead.

Still stuck? Help me troubleshoot my Flask app not responding on localhost.

Your API is working locally. Next up, you'll deploy it live to Azure so anyone on the internet can access it.

Deploy to Azure with the CLI

Your API works on your machine. Now it's time to put it on the internet where anyone can access it.

Azure App Service is a Platform-as-a-Service that runs your web apps without you managing servers. You'll deploy your Flask API with a single Azure CLI command that creates everything you need automatically.

In this step, get ready to:
  • Deploy your Flask API to Azure App Service with one command.
  • Visit your live URL in the browser and confirm the API responds.
  • Explore the Azure Portal to see the resources Azure created for you.
Deploy your API with az webapp up

The az webapp up command is a shortcut that creates a resource group, an App Service Plan, and a web app all in one step. It packages your current directory and deploys it to Azure.

Your app name must be globally unique because it becomes part of your public URL. Pick something like wa-agency-api-yourname (replacing yourname with your actual name).

  • Make sure you are inside the wa-agency-api/ directory (where app.py lives).
  • Deploy your API to Azure by running this command:
az webapp up --runtime PYTHON:3.13 --sku F1 --name [[APP_NAME="your-unique-app-name"]]

What does this command do?

  • --runtime PYTHON:3.13 tells Azure to run your app with Python 3.13.
  • --sku F1 selects the free tier (F1). This costs $0 and gives you 60 CPU minutes per day.
  • --name sets your app's unique name, which becomes the public URL.
  • Azure automatically creates a resource group, an App Service Plan, and the web app itself.

This command takes 1-2 minutes to finish. When it completes, you'll see JSON output in your terminal showing your app's details, including the URL.

  • Look for the URL in the JSON output. It will be in the format https://your-app-name.azurewebsites.net.

Seeing a name conflict error?

  • If you see a message about the name already being taken, your app name is not globally unique. Try adding numbers or your initials to make it unique.
  • Make sure you are inside the wa-agency-api/ folder. The command deploys the current directory, so it needs to find app.py and requirements.txt in the folder you run it from.
  • If you see an authentication error, run az login again to refresh your session.

Help me troubleshoot my az webapp up deployment

Visit your live app in the browser

Your API is now live on the internet. Time to confirm it works from outside your machine.

  • Copy the URL from the terminal output (the https://your-app-name.azurewebsites.net value).
  • Paste it into your browser's address bar and press Enter.

You should see the JSON response from your home route:

{"message":"WA State Agency API","version":"1.0"}
  • Try the /agencies endpoint too. Add /agencies to the end of your URL and press Enter.

You should see the full list of WA state agencies in JSON format, just like when you tested locally.

Why does this work without any server setup?

Azure App Service detected your requirements.txt, installed Flask automatically, and started your app. You never configured a web server, set up networking, or opened firewall ports. That's the power of Platform-as-a-Service.

Seeing an application error page?

  • Give it 30 seconds and refresh. The first load after deployment can be slow while Azure starts your app.
  • Check that your app.py has no syntax errors. If the app crashes on startup, Azure shows a generic error page.
  • Verify your requirements.txt contains Flask==3.1.3. Missing dependencies prevent the app from starting.

Help me debug my Azure App Service deployment

Explore the Azure Portal to see your resources

The CLI created three resources behind the scenes. Seeing them in the Azure Portal helps you understand what you're managing.

  • Open your browser and go to portal.azure.com.
  • In the left navigation pane, click Resource groups.
  • Click on the resource group that was created (its name matches your app name or region).

Inside the resource group, you should see three resources:

  • App Service Plan (type: App Service plan). This defines the compute tier (F1 free) and the operating system (Linux).
  • App Service (type: App Service). This is your running web app.
  • Resource group itself. This is the container that holds the other two resources together.

Why do resource groups matter?

A resource group is a logical container for related Azure resources. When you delete the resource group, everything inside it gets deleted too. This makes cleanup simple and prevents orphaned resources from running up costs.

In government cloud environments, resource groups also provide a boundary for access control and cost tracking. Teams can manage permissions and budgets per resource group.

Your API is live and you've seen the resources Azure built for you. Next up, you'll define this same infrastructure as code with Bicep so it's repeatable and auditable.

Define Infrastructure as Code with Bicep

In the last step, you deployed your API to Azure using the CLI. It worked, but everything happened behind the scenes. If someone asked you exactly what infrastructure is running, you'd have to poke around the portal to find out.

In this step, you'll define the same infrastructure in a Bicep template. Bicep is Azure's native Infrastructure as Code language. It lets you describe your cloud resources in a file that's version-controlled, reviewable, and deployable with a single command.

In this step, get ready to:
  • Create a Bicep template defining your App Service infrastructure.
  • Deploy the template to Azure with one command.
  • Verify your Bicep-deployed resources and understand why IaC matters for government.
Create the Bicep template file

Your Bicep file will declare the same two resources that az webapp up created automatically: an App Service Plan and a Web App. The difference is that now the infrastructure is written down, readable, and repeatable.

  • Create a new file called main.bicep in your wa-agency-api folder by running this command:
touch main.bicep
  • Confirm the file exists by running:
ls

You should see main.bicep alongside app.py and requirements.txt in the output.

  • Open main.bicep in VS Code and add the parameters and App Service Plan resource:
param location string = resourceGroup().location
param appName string
param appServicePlanName string = '${appName}-plan'

resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: appServicePlanName
  location: location
  kind: 'linux'
  properties: {
    reserved: true
  }
  sku: {
    name: 'F1'
  }
}

What does this code do?

The param lines declare inputs your template needs. location defaults to wherever the resource group lives. appName has no default, so you'll pass it at deploy time.

The appServicePlan resource defines a Linux App Service Plan on the free F1 tier. reserved: true tells Azure this plan runs Linux containers. kind: 'linux' confirms the OS type.

The API version 2023-12-01 tells Azure which resource provider schema to use.

  • Below the appServicePlan resource, add the Web App resource and output:
resource webApp 'Microsoft.Web/sites@2023-12-01' = {
  name: appName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'PYTHON|3.13'
    }
    httpsOnly: true
  }
}

output appUrl string = 'https://${webApp.properties.defaultHostName}'

What does this code do?

The webApp resource defines your actual web application. serverFarmId: appServicePlan.id links it to the plan you defined above. Bicep automatically resolves this reference.

The linuxFxVersion: 'PYTHON|3.13' tells Azure to use the Python 3.13 runtime. httpsOnly: true forces all traffic over HTTPS.

The output line prints your app's URL after deployment completes, so you don't have to look it up.

  • Save main.bicep.

Seeing red squiggles in VS Code?

Make sure the Bicep VS Code extension is installed from Step 1. Red underlines usually mean a typo in a resource type name or a mismatched brace. Check that Microsoft.Web/serverfarms@2023-12-01 and Microsoft.Web/sites@2023-12-01 are spelled exactly as shown.

Having trouble? Help me fix Bicep syntax errors in my main.bicep file

✔️ Awesome, I've got everything!

Great. Double check you've saved main.bicep before moving on.

ⓧ I'd like to double check the full code

Here's the complete main.bicep file for comparison:

param location string = resourceGroup().location
param appName string
param appServicePlanName string = '${appName}-plan'

resource appServicePlan 'Microsoft.Web/serverfarms@2023-12-01' = {
  name: appServicePlanName
  location: location
  kind: 'linux'
  properties: {
    reserved: true
  }
  sku: {
    name: 'F1'
  }
}

resource webApp 'Microsoft.Web/sites@2023-12-01' = {
  name: appName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'PYTHON|3.13'
    }
    httpsOnly: true
  }
}

output appUrl string = 'https://${webApp.properties.defaultHostName}'

Why Bicep instead of Terraform?

Bicep is Azure-native. It ships with the Azure CLI (no extra install), integrates directly with Azure Resource Manager, and is the language Microsoft uses in all its official IaC documentation.

Terraform is cloud-agnostic and powerful, but adds complexity. For someone targeting Azure-heavy Washington state government roles, Bicep is the more relevant skill. WaTech-managed environments use Azure Resource Manager natively.

Deploy the Bicep template to Azure

Your template is ready. Now you'll deploy it to the same resource group where your app already lives. This tells Azure to match the real infrastructure to what your file describes.

  • First, find your resource group name. Run this command to list your resource groups:
az group list --output table

Look for the resource group that was created in the previous step. It will contain your app name. Note the name down.

  • Deploy your Bicep template by running this command:
az deployment group create --resource-group [[RESOURCE_GROUP="your-resource-group-name"]] --template-file main.bicep --parameters appName=[[APP_NAME="your-unique-app-name"]]

What does this command do?

This command tells Azure Resource Manager to read your main.bicep file and ensure the described resources exist. --resource-group targets the group where resources land. --parameters appName=... passes the required app name to your template.

Use the same app name you chose in the previous step. Azure will detect that the resources already exist and update them to match the template rather than creating duplicates.

The deployment takes about 30 to 60 seconds. You'll see a JSON output when it finishes, including your appUrl output value.

  • Copy the URL from the appUrl output and open it in your browser.
  • Confirm you see the same JSON response: {"message":"WA State Agency API","version":"1.0"}.

Deployment failed?

If you see an error about the app name already existing in a different resource group, make sure you're using the exact same app name from the previous step.

If you see an error about the resource group not being found, double check the name matches what az group list --output table showed you.

Still stuck? Help me troubleshoot my Bicep deployment error

Verify resources and understand why IaC matters

Your Bicep template now manages the same infrastructure you created manually. Let's confirm that in the Azure Portal and connect this to the bigger picture.

  • Open the Azure Portal at portal.azure.com in your browser.
  • Click on Resource groups in the left sidebar.
  • Click your resource group name.
  • Verify you see two resources: your App Service Plan and your Web App.

These are the same resources that existed before, but now they're defined in code. If you ever deleted them accidentally, you could recreate them with one command.

Why does IaC matter for government roles?

Washington state agencies like WaTech and DES require strict compliance and auditability. When infrastructure is defined in code, every change is tracked in version control. Auditors can review exactly what's deployed without logging into the portal.

Repeatability matters too. If a disaster recovery scenario requires rebuilding an environment, a Bicep template gets you there in minutes instead of hours of manual clicking. Compliance teams can review main.bicep as part of a pull request, just like application code.

Your infrastructure is now fully defined in code. In the Secret Mission, you'll extend this template with monitoring and diagnostics. But even at this point, you have something impressive: a live API backed by a repeatable, auditable deployment template.

Secret mission

Add Monitoring and a Health Check

Your API is live, but can you tell if it's healthy? In production, every service needs a health check endpoint and proper logging. Add a /health endpoint that reports system status, then enable Azure diagnostic logging so you can watch requests hit your API in real time.

Clean Up Your Resources

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project uses the Azure App Service F1 (Free) tier, which costs $0 indefinitely.

Resources you used:

  • Azure Resource Group (contains your App Service Plan and Web App).
  • Local project files (app.py, requirements.txt, main.bicep).
  • Python 3.13 (installed via Homebrew).
  • Azure CLI (installed via Homebrew).
  • Bicep VS Code extension.

Keep everything running

No action needed. Choose this if you want your API to stay live on the internet or plan to build more Azure projects.

  • Your app continues running at its .azurewebsites.net URL at zero cost on the F1 free tier.
  • The F1 tier has no expiry date and no credit card charges.
  • Python 3.13, Azure CLI, and the Bicep extension remain installed on your machine for future projects.

Pause - I'll come back to this later

Since the F1 tier is already free, there is nothing to pause from a cost perspective. Your app costs $0 whether it receives traffic or not.

  • Leave everything as-is. When you return, your app will still be running at the same URL.
  • Your local project files and installed tools stay in place for when you are ready to continue.

Delete - I don't want to use this again

Remove all Azure resources and local project files to start completely fresh.

Delete your Azure Resource Group (this removes the App Service Plan and Web App in one command):

  • Delete your entire resource group by running:
az group delete --name [[RESOURCEGROUP="your-resource-group-name"]] --yes

What does this command do?

The --yes flag skips the confirmation prompt. This permanently deletes the resource group and everything inside it (App Service Plan, Web App, and all diagnostic logging configuration).

Delete your local project files:

  • Remove your project folder from the Desktop by running:
cd ~/Desktop
rm -rf [[PROJECTFOLDER="your-project-folder-name"]]

On Windows, use this instead:

cd ~\Desktop
rmdir /s /q [[PROJECTFOLDER="your-project-folder-name"]]

Uninstall Python 3.13 and Azure CLI (optional):

  • Uninstall Python 3.13 from Homebrew by running:
brew uninstall python@3.13
  • Uninstall the Azure CLI from Homebrew by running:
brew uninstall azure-cli

Uninstall the Bicep VS Code extension:

  • In VS Code, open the Extensions sidebar by pressing Cmd+Shift+X (macOS) or Ctrl+Shift+X (Windows).
  • Search for Bicep, click on the extension, and click Uninstall.

Nice Work!

Nice Work!

You just deployed a cloud application using the same tools and patterns that WA state government teams use daily. You now have a live REST API on the internet and a repeatable Infrastructure as Code template to prove it.

You've learned how to:

  • Built a Python Flask REST API from scratch with multiple endpoints.
  • Deployed it live to Azure App Service using the Azure CLI.
  • Defined your infrastructure as code using Bicep, making your cloud resources repeatable and auditable.
  • Secret Mission: Added a health check endpoint, enabled diagnostic logging, and streamed live logs to monitor your API in real time.

Ready to quiz yourself?