Azure Functions timeout: don't wait for an AI video job

Azure Functions time out after 5 minutes by default on Consumption, and HTTP triggers must answer in 230 seconds. Submit video jobs with a callback.

6 min readSume
All posts

An Azure Functions timeout comes from the function app's functionTimeout: 5 minutes by default and 10 at most on the legacy Consumption plan, and 30 minutes by default on the Flex Consumption, Premium, and Dedicated plans, where the maximum can be unbounded. Separately, an HTTP-triggered function has 230 seconds to respond, whatever the setting. AI video generation typically takes 30 seconds to several minutes, so don't wait for it inside a function: submit the job with a callback_url that points at a second HTTP-triggered function, and return.

Azure facts come from Microsoft Learn's hosting options, host.json, HTTP trigger, error handling, and reliability pages; Sume facts from Video Generation, Jobs and results, and Webhooks. All were read on 2026-09-27. Sume has no Azure connector: your functions call its HTTPS API. The same problem on Vercel is covered in Vercel function timeout on video generation.

How long can an Azure Function run?

Set the limit with functionTimeout in host.json, in the [d.]hh:mm:ss format; -1 means unbounded, though Microsoft recommends keeping a fixed upper bound. When an execution runs past it, a timeout error occurs and the language worker process restarts. The HTTP limit is separate: an HTTP-triggered function that doesn't complete within 230 seconds gets a 502 from Azure Load Balancer, and keeps running without being able to respond.

From Microsoft Learn's function app timeout duration table and HTTP trigger limits, read 2026-09-27.
PlanDefaultMaximum
Flex Consumption30 minutesUnbounded
Premium30 minutesUnbounded
Dedicated30 minutesUnbounded, with Always On
Container Apps30 minutesUnbounded
Consumption (legacy)5 minutes10 minutes
HTTP trigger response, any plan—230 seconds

What happens to the video when my function times out?

Nothing stops it. A client-side timeout doesn't cancel a Sume job: it keeps running and still bills, and you have only stopped watching. A 2xx from the submit means the job exists and paid work is in flight, not that it finished.

Retries are the costly part. Queue Storage triggers retry through their extension, and timer triggers can take a retry policy, so the same submit can run again after a timeout. Sume's docs say not to resubmit a paid request just because your worker timed out, and to send an Idempotency-Key on every paid submit that may be retried: a replay returns the original job. Same key, same body; a key reused with a different payload is 409 idempotency_conflict.

How do I submit the job without waiting?

Submit, store the id, return. This Python v2 function answers in the time one HTTPS call takes:

  • callback_url must be a public HTTPS URL; Sume POSTs to it once the job reaches a terminal state.
  • Store the job id from the 202 response. Sume's docs say it lets you recover work after a process restart.
  • Keep SUME_API_KEY in app settings, or as a Key Vault reference, which your code reads like any other app setting; app settings reach your code as environment variables.
  • Requests doesn't time out unless you pass timeout, so set one on the submit.
import os, requests
import azure.functions as func

app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

@app.route(route="videos", methods=[func.HttpMethod.POST])
def start_video(req: func.HttpRequest) -> func.HttpResponse:
    order_id = req.params.get("order_id")
    if not order_id:
        return func.HttpResponse("order_id is required", status_code=400)
    r = requests.post(
        "https://api.sume.com/v1/videos",
        headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
                 "Idempotency-Key": f"order-{order_id}-video-v1"},
        json={"model": "sume/auto", "prompt": "A slow pan across a desk, morning light",
              "callback_url": "https://<app-name>.azurewebsites.net/api/sume-webhook"},
        timeout=30,
    )
    r.raise_for_status()
    job = r.json()  # id, polling_url, status: "pending", model
    save_job(order_id, job["id"])  # your table, before you return
    return func.HttpResponse(job["id"], status_code=202)

How does the second function receive the result?

Make it an HTTP trigger with the anonymous auth level and check Sume's signature instead of an Azure key. Sume sends terminal job events only, job.completed, job.failed, or job.canceled, gives each attempt 10 seconds, and makes up to 10 attempts. The full Python check is in Durable Functions wait for external event.

  • Verify the raw bytes from req.get_body(): refuse an empty signing secret, then check HMAC-SHA256 over <timestamp>.<raw_body>, a match on any sume-v1= entry compared in constant time, and a five-minute timestamp window.
  • Store the event, then answer 2xx. For slower work, Microsoft suggests passing the HTTP payload to a queue for a queue-triggered function, so the webhook can respond immediately.
  • Use job_id as your idempotency key, since non-2xx answers and network errors are retried.
  • Keep polling as the backup. Ten refused attempts leave a failed delivery and a job that still reached its terminal state.

Should I raise the timeout or use Durable Functions?

Raising functionTimeout on a Premium or Flex Consumption plan lets one execution run longer, but an HTTP trigger still has to respond within 230 seconds, and the function sits idle while the video renders. Microsoft's own advice for longer processing is the Durable Functions async pattern, or deferring the work and returning an immediate response. With Durable Functions, an orchestrator can wait for the webhook as an external event without being billed for the wait on the Consumption plan; see Durable Functions wait for external event.

Sources

Related posts

More in Integrations

All Integrations posts

Written by Sume