<@ULVA73B9P> I'm looking to set up a Azure Contain...
# ask-marvin
v
@Marvin I'm looking to set up a Azure Container Instances work pool. I have a high frequency tasks that runs every minute and I want to make sure that the container is always available for new run and there's as little overtime
m
thought for 751.4 seconds
Great question — and perfect use case to think about startup latency. Assuming Prefect 3.x, here’s how to set up an Azure Container Instances (ACI) work pool and what to expect for a flow that runs every minute, plus options to minimize “overtime”. Key takeaway up front: ACI workers create a new container group per flow run and tear it down when the run finishes. There isn’t a built-in “keep the container warm” setting; each run incurs provisioning time. For true always-warm execution, consider one of the alternatives at the bottom. Links you’ll likely want: - ACI worker docs: Prefect 3 ACI worker - Work pools overview: Work pools - Deployments: Deploy flows in Prefect 3 Setup steps (ACI worker) 1) Install Prefect with Azure extras (on the machine that will run the worker)
Copy code
pip install "prefect[azure]"
2) Azure prerequisites and permissions - Resource group in the region you want ACI to run - Container image in ACR (same region as the RG if possible) - Service principal or managed identity with: - Container Instance Contributor (or Contributor) on the resource group - AcrPull on the ACR - Network Contributor on the subnet if you’ll attach a VNet - If using a service principal, set these environment variables where you’ll run the worker:
Copy code
export AZURE_TENANT_ID=...
export AZURE_CLIENT_ID=...
export AZURE_CLIENT_SECRET=...
3) Create an ACI work pool
Copy code
prefect work-pool create aci-pool --type azure-container-instance
Tip: Inspect the ACI job template variables you can set:
Copy code
prefect work-pool get-default-base-job-template --type azure-container-instance
You’ll see fields like resource_group_name, subscription_id, image, image_registry, cpu, memory, subnet_ids, identities, dns_servers, env, task_start_timeout_seconds, etc. 4) Start a worker that polls the pool Run this from a machine (or container app/VM) with the Azure credentials above:
Copy code
prefect worker start --pool aci-pool
5) Deploy your flow to the ACI pool with per-run variables Here’s a minimal example using the programmatic deployment API. Note the job_variables aligned to the ACI worker’s template.
Copy code
from prefect import flow

@flow
def my_job():
    # your minute-level work here
    ...

if __name__ == "__main__":
    my_job.deploy(
        name="every-minute",
        work_pool_name="aci-pool",
        interval=60,  # run every minute
        concurrency_limit=1,  # ensure only one active run if that’s desired
        job_variables={
            "subscription_id": "<your-subscription-id>",
            "resource_group_name": "<your-rg>",
            "image": "<http://myregistry.azurecr.io/myimage:tag|myregistry.azurecr.io/myimage:tag>",
            # If using ACR username/password:
            "image_registry": {
                "registry": "<http://myregistry.azurecr.io|myregistry.azurecr.io>",
                "username": "<acr-username-or-app-id>",
                "password": "<acr-password-or-sp-secret>"
            },
            # Or prefer identities (user-assigned MI resource IDs) if supported in your setup:
            # "identities": ["/subscriptions/.../resourcegroups/.../providers/Microsoft.ManagedIdentity/userAssignedIdentities/<name>"],
            "cpu": 0.5,
            "memory": 1.0,
            # Optional networking:
            # "subnet_ids": ["/subscriptions/.../resourceGroups/.../providers/Microsoft.Network/virtualNetworks/.../subnets/..."],
            # Optional environment variables for your code:
            "env": {"MY_APP_SETTING": "value"},
            # Operational tuning (does not reduce cold start, but helps robustness):
            # "task_start_timeout_seconds": 600,
            # "task_watch_poll_interval": 5,
        },
    )
What to expect for latency and “overtime” - ACI cold start includes: - Provisioning the container group: commonly ~15–60s
- Pulling the image: depends on size and caching; can add seconds to minutes - Because the worker deletes the container group after each run, there’s no native warm cache for the next run. For a schedule every minute, you may see runs frequently overlap or go “overtime” if total startup + execution > 60s. How to reduce latency if you must stay on ACI - Keep images small and hosted in ACR in the same region as the RG - Prefer regional proximity for everything (RG, ACR, VNet) - Use managed identities or a minimal pull secret path to avoid slow auth - Avoid attaching a VNet unless required (it adds provisioning steps) - If occasional overlap is acceptable, set a higher work pool concurrency and make your flow idempotent - Consider disabling schedule catch-up to avoid backlogs if a few runs are slow Patterns to keep containers “always available” (recommended for minute-level jobs) If you want near-zero startup overhead per run, ACI is not ideal. Options: - Run a persistent worker on your own compute and use a Process or Docker work pool - Start a worker on a VM or Azure Container Apps (ACA) with min replicas = 1. The compute stays warm; your deployment uses the process or docker pool for instant starts. - Use a long-running “resident” flow pattern - Instead of scheduling every minute, run a single flow/container that loops internally:
Copy code
from prefect import flow
  import time

  @flow
  def daemon():
      while True:
          try:
              # do work
              pass
          finally:
              time.sleep(60)
- This keeps the container alive and eliminates per-run cold starts. You can still use Prefect for logging, retries, and orchestration signals, but it’s one long-lived run. - Consider Kubernetes or Azure Container Apps Jobs with pre-warmed capacity - If you already have AKS, a Kubernetes worker can start pods quickly (especially with image pre-pull and node autoscaling tuned). - On ACA, you can run the Prefect worker as a always-on service and point deployments to a process/docker pool. A couple of quick questions to tailor this: - Is ACI a hard requirement for you, or are you open to a persistent worker (VM/ACA) to keep compute warm? - Do you need VNet/private networking for the job? That can influence startup time and config. - What’s your image size today and where is it hosted? If you confirm ACI is required, I can help you pin down the exact job_variables for your networking/identity setup and review your image and registry placement to minimize cold starts.