Skip to content

Add an Azure preview stack, plus the two app fixes it uncovered - #134

Merged
lionello merged 2 commits into
mainfrom
azure-preview
Sep 7, 2026
Merged

Add an Azure preview stack, plus the two app fixes it uncovered#134
lionello merged 2 commits into
mainfrom
azure-preview

Conversation

@defangdevs

Copy link
Copy Markdown
Contributor

Groundwork for #126. Rather than migrating production blind — deploy.yaml runs only on push to main, so there is no way to try a change before users see it — this adds a preview stack and reports what deploying it found.

The preview is an overlay, not a copy

compose.preview.yaml uses extends to pull services out of compose.yaml, so production and preview cannot drift:

defang compose up -s preview -f compose.preview.yaml

Three deliberate differences, each of which would otherwise damage production:

  • discord-bot is left out. It carries the live Discord token; a second copy would answer real users alongside production. Compose overlays can add and change keys but cannot delete a service, so selecting services via extends is the only way to drop one.
  • domainname is cleared ("" clears the inherited value — verified in the rendered config). A preview must never claim ask.defang.io or race production for its certificate.
  • The model alias is llm. On Azure the AI Foundry deployment is named after the service while Defang wires the alias into MODEL; a mismatch is DeploymentNotFound at runtime. fix(azure): probe delay clamp, LLM alias lookup, and self-destruct name collision pulumi-defang#536 fixes the provider side, after which this becomes the portable chat-default.

.defang/preview carries the Azure settings. Two things worth knowing: DEFANG_MODE=balanced is tier-gated ("this recipe is not available for your tier"), and AZURE_CLIENT_ID must be absent locally or it tries to use the CI identity.

Verified rendered output: preview has neither domainname nor discord-bot; production still has both and its Bedrock model.

Two app fixes the preview found

Both are real bugs against GPT-5.1 that Bedrock never exposed, and both would have broken the migration on merge:

  1. max_tokens is rejected: "Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead."
  2. Azure opens a stream with an empty choices list (it carries prompt_filter_results), and emits more choice-less chunks for content filtering. chunk["choices"][0] raised IndexError and killed the answer mid-stream.

One portability fix in the base compose

start_period: 240s exceeds Azure's 60s cap on a probe's InitialDelaySeconds and fails the deploy outright with ContainerAppProbeInitialDelaySecondsOutOfRange. Now 60s with retries raised to 10, keeping the startup budget at 360s (was 390s) and staying equivalent on ECS, where start_period is a grace window.

Verified end to end

Deployed to Azure and confirmed answering a real question through /ask (CSRF + proof-of-work), on gpt-5.1 — worth flagging for #126, since that is a step up from Claude Haiku 4.5 rather than the like-for-like swap the issue asked about, and the model is chosen from a fixed preference list with no way to request a tier. Stack has been torn down.

Two Defang-side defects remain and are fixed in pulumi-defang#536 and #538 (the LLM deployment defaulted to 1K TPM, below the cost of a single RAG request).

Refs #126

The preview is an overlay rather than an edited copy of compose.yaml, so it
stays in sync with production. extends selects only the services a preview
should run, which is how discord-bot (live Discord token) is left out.

Deploying it surfaced two app bugs against GPT-5.1 on Azure that Bedrock had
never exposed: max_tokens is rejected in favour of max_completion_tokens, and
Azure opens a stream with a chunk whose choices list is empty.
Comment thread .defang/preview
Comment thread compose.yaml
@lionello

lionello commented Sep 7, 2026

Copy link
Copy Markdown
Member

@defangdevs what about #130??

Lio's review suggestion on PR #134: a forgotten preview stack should
self-destruct rather than run forever. No effect yet — the feature
needs a pulumi-defang release past PR 536, blocked on #414
(RELEASE_PAT) — but harmless to set now.
@defangdevs

Copy link
Copy Markdown
Contributor Author

Re DEFANG_TTL and the start_period workaround: replied inline, both addressed (added TTL; follow-up #137 to revert the workaround once pulumi-defang releases past #536).

On #130: it's being reworked right now onto the `models:` compose migration (it currently predates that and hand-sets `MODEL`). That rework is carrying the same Azure fixes from here, and I'm told it's just been verified end-to-end against a live preview deploy. Update on it should follow shortly — hold off reviewing #130 until that lands.

defangdevs added a commit that referenced this pull request Sep 7, 2026
- compose.yaml: Azure Container Apps caps a probe's InitialDelaySeconds at
  60, and Defang maps start_period onto it, so the inherited 240s failed
  the deploy outright with ContainerAppProbeInitialDelaySecondsOutOfRange.
  Keep the startup budget inside that limit (60 + 10*30 = 360s); ECS
  treats start_period as a grace window, so this stays equivalent there.
- app/rag_system.py: two real bugs against GPT-5.1 that Bedrock never
  exposed, found via a live Azure preview deploy: max_tokens is rejected
  in favor of max_completion_tokens, and Azure opens a stream with a
  chunk whose choices list is empty (content filtering), which raised
  IndexError and killed the answer mid-stream.

Verified end to end against a throwaway Azure preview stack: Deploy
succeeds, the llm service provisions via Azure AI Foundry with MODEL
correctly wired to the "llm" deployment alias, and /v1/ask answers
correctly on gpt-5.1. Stack has been torn down.

Same fixes as #134, ported here so this PR is
correct standalone regardless of merge order between the two.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MPfV4G82XiSnHVUhyqXzXv
@defangdevs

Copy link
Copy Markdown
Contributor Author

@lionello re merge order between this PR and #130 — direct answer:

Merge #134 first. It's already approved and doesn't depend on the Azure migration landing: the start_period/max_completion_tokens/empty-choices fixes are safe on the current AWS/Bedrock production too (LiteLLM's --drop_params keeps max_completion_tokens safe on Bedrock; ECS treats start_period as a grace window the same way Azure's probe delay does), and compose.preview.yaml + .defang/preview is reusable preview-stack tooling worth having on its own, not just for this migration.

#130 already carries the identical two fixes — ported in deliberately so it stays correct standalone while it's blocked on the federated-credential/pulumi up step — so once #134 merges, rebasing #130 onto main should be a clean no-op on compose.yaml/rag_system.py, not a real conflict to untangle.

Don't close either as a duplicate. They're doing different jobs that happen to overlap on two bug fixes: #134 is reusable groundwork (preview-stack tooling for future changes, plus the app/portability fixes), #130 is the actual migration (deploy.yaml's OIDC switch, .defang/production, dropping x-defang-dns-role).

Separately: #130 is still blocked on defang-mvp#3225's federated credential actually being applied (pulumi up --stack defang) before its own Deploy step can be verified for real — I've asked for that on the PR (and on #3225). That's unrelated to this merge-order question and will keep #130 in draft a little longer regardless of #134's fate.

@lionello
lionello merged commit 7f8f29b into main Sep 7, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants