Skip to main content

Azure AD B2C Custom Policy: Single Relying Party with Separate Sign-In and Sign-Up Links

One Relying Party file. One combined page. But your application needs a standalone Sign-Up link that bypasses the combined UI and goes directly to registration. Here is the complete solution using the OAUTH-KV claim resolver and orchestration step preconditions — no duplicate RP files required.

1 RP file
Single Relying Party policy handles sign-in, sign-up, forgot password, and direct sign-up link
OAUTH-KV
Claim resolver that reads a custom query string parameter from the authorization request
Precondition
Orchestration step preconditions branch the user journey based on the action= query parameter value
?action=signup
The query parameter your app passes to signal a direct sign-up — bypass the combined page entirely
ℹ Azure AD B2C Availability Note

As of 1 May 2025, Azure AD B2C is no longer available to new customers. Existing tenants continue to operate, and this guide applies to all existing B2C tenants using custom policies. New identity implementations should evaluate Microsoft Entra External ID as the successor platform. The architectural patterns in this guide (OAUTH-KV claim resolvers, orchestration step preconditions) also apply to Entra External ID custom policies.

Understanding the Problem

Why a Standalone Sign-Up Link Does Not Work Out of the Box

The CombinedSignInAndSignUp orchestration step is the standard mechanism for presenting a single UI page that handles both authentication paths. When a user arrives at the page, the sign-in tab is active by default. There is a "Sign up now" link at the bottom of the page that users can click to switch to the registration form — but the default entry point always starts in sign-in mode.

The problem arises when your application needs to provide a standalone "Sign Up" link — a button on your home page or marketing site that takes users directly to the registration form without going through the combined page. By default, invoking the single RP policy always starts in sign-in mode regardless of what your application intends. Passing a custom query parameter like ?action=signup in the authorization URL has no effect out of the box — the Identity Experience Framework (IEF) does not read custom query parameters unless you explicitly configure it to do so.

The solution involves two things working together: the OAUTH-KV claim resolver (which extracts the custom query parameter from the OAuth 2.0 authorization request and maps it to a claim), and orchestration step preconditions (which evaluate the claim value and branch the user journey accordingly). Together, they let a single Relying Party policy produce different user journey paths based on what the application signals in the authorization URL.

Figure 1 — Complete architecture: single RP policy with three user journey paths from one authorization endpoint
Sign In linkSign Up linkForgot PasswordAPPLICATIONno ?action=?action=signupsame RP policyB2C_1A_Signup_SigninSingle RP fileOAUTH-KV:action claimPrecondition evaluationJourney branchingCombinedSignInAndSignUp pageSign-in tab active · "Sign up now" link availablePrecondition: clientActionIntent ≠ 'signup' (or absent)Direct Sign-Up page (SelfAsserted)Registration form shown immediatelyPrecondition: clientActionIntent = 'signup'Forgot Password (Sub-Journey)Triggered by "Forgot password" link on combined pageInvokeSubJourney orchestration stepAll paths → JWT Token issuedSame RP file · Same claims output · Same redirect_uriSingle policy to maintain · No policy sprawlBENEFITS✓ Zero policy sprawl✓ Single maintenance point✓ Centralised business rules✓ Same client_id / redirect_uri
All three user journeys (combined sign-in/sign-up, direct sign-up, forgot password) are served by a single Relying Party file — the OAUTH-KV claim resolver reads the ?action= parameter to decide which path to take
The Implementation

The Complete Implementation — Four XML Changes to Your Policy Files

The solution requires four changes spread across your policy files: declare the claim type in the ClaimsSchema, populate it from the OAUTH-KV resolver in the RP file, add the direct sign-up orchestration step to the user journey in Extensions, and add the precondition that skips the combined step when the claim equals "signup". Forgot Password continues to work as a sub-journey from within the combined page — no changes needed there.

1

Step 1 — Declare the claim type in TrustFrameworkExtensions.xml

Add the clientActionIntent claim type to your ClaimsSchema. This claim will hold the value of the ?action= query string parameter sent by your application. It is a plain string claim with no special constraints — it will be populated by the OAUTH-KV resolver in the next step and then evaluated by preconditions in the user journey.

Place this inside the <BuildingBlocks> <ClaimsSchema> element in your TrustFrameworkExtensions.xml or the policy file where you define your claims schema.

TrustFrameworkExtensions.xml — Step 1: Declare the clientActionIntent claim type<!-- Inside <BuildingBlocks><ClaimsSchema> -->

<ClaimType Id="clientActionIntent">
  <DisplayName>Client Action Intent</DisplayName>
  <DataType>string</DataType>
  <UserHelpText>Action intent passed by the relying party application (e.g. signup)</UserHelpText>
</ClaimType>

<!-- This claim will receive the value of ?action= from the OAuth2 authorization request -->
<!-- When action=signup is passed, it drives the precondition in the user journey -->
2

Step 2 — Populate the claim from the OAUTH-KV resolver in the Relying Party file

In your Relying Party (RP) XML file — typically named B2C_1A_Signup_Signin.xml or similar — add an InputClaim that uses the {OAUTH-KV:action} resolver as its DefaultValue. The OAUTH-KV claim resolver extracts the value of any custom query parameter passed in the OAuth 2.0 authorization request. {OAUTH-KV:action} reads ?action=signup from the URL and maps it to the clientActionIntent claim.

The AlwaysUseDefaultValue="true" attribute is critical — without it, the resolver only populates the claim if no prior value exists. With it, the resolver always overwrites the claim with the current request's value, which is what you need.

SignUpSignIn.xml (RP file) — Step 2: Map the OAUTH-KV claim resolver to clientActionIntent<!-- Inside <RelyingParty> -->

<RelyingParty>
  <DefaultUserJourney ReferenceId="SignUpOrSignIn" />

  <TechnicalProfile Id="PolicyProfile">
    <DisplayName>PolicyProfile</DisplayName>
    <Protocol Name="OpenIdConnect" />

    <InputClaims>
      <!-- Read the ?action= query parameter from the OAuth2 authorization request -->
      <!-- {OAUTH-KV:action} maps the &action= URL param to clientActionIntent claim -->
      <InputClaim
        ClaimTypeReferenceId="clientActionIntent"
        DefaultValue="{OAUTH-KV:action}"
        AlwaysUseDefaultValue="true" />
    </InputClaims>

    <OutputClaims>
      <!-- Your existing output claims (objectId, email, displayName, etc.) -->
      <OutputClaim ClaimTypeReferenceId="displayName" />
      <OutputClaim ClaimTypeReferenceId="email" />
      <OutputClaim ClaimTypeReferenceId="objectId" PartnerClaimType="sub" />
      <!-- clientActionIntent is NOT included in output claims -->
      <!-- It is internal routing only — do not expose it in the JWT token -->
    </OutputClaims>
    <SubjectNamingInfo ClaimType="sub" />
  </TechnicalProfile>
</RelyingParty>
3

Step 3 — Modify the user journey with branching orchestration steps

This is the core of the solution. The user journey needs two orchestration steps at the beginning — one for the direct sign-up path (skipped unless clientActionIntent = signup) and one for the combined sign-in/sign-up path (skipped if clientActionIntent = signup). The preconditions on each step control which path runs.

The combined step uses a ClaimEquals precondition: if clientActionIntent equals signup, skip this step (and show the direct sign-up instead). The direct sign-up step uses the inverse: skip it unless clientActionIntent equals signup.

The Forgot Password sub-journey remains on the combined step — it is triggered by the user clicking "Forgot password" on the combined UI, not by the query parameter.

TrustFrameworkExtensions.xml — Step 3: User journey with branching preconditions<!-- Inside <UserJourneys> -->

<UserJourney Id="SignUpOrSignIn">
  <OrchestrationSteps>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 1 — Direct Sign-Up (only runs when action=signup is passed) -->
    <!-- Skip this step if clientActionIntent is absent OR not equal to signup -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="1" Type="ClaimsExchange">
      <Preconditions>
        <!-- Skip if clientActionIntent claim does not exist at all -->
        <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
          <Value>clientActionIntent</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
        <!-- Skip if clientActionIntent exists but is NOT 'signup' -->
        <Precondition Type="ClaimEquals" ExecuteActionsIf="false">
          <Value>clientActionIntent</Value>
          <Value>signup</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <!-- This technical profile shows only the sign-up/registration form -->
        <ClaimsExchange
          Id="DirectSignUpWithLocalAccount"
          TechnicalProfileReferenceId="LocalAccountSignUpWithLogonEmail" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 2 — Combined Sign-In / Sign-Up (normal entry point) -->
    <!-- Skip this step if action=signup was passed (direct signup ran in Step 1) -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="2" Type="CombinedSignInAndSignUp" ContentDefinitionReferenceId="api.signuporsignin">
      <Preconditions>
        <!-- Skip the combined page if the user already completed direct sign-up in Step 1 -->
        <!-- After LocalAccountSignUpWithLogonEmail, objectId will be in the claims bag -->
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsProviderSelections>
        <ClaimsProviderSelection ValidationClaimsExchangeId="LocalAccountSigninEmailExchange" />
      </ClaimsProviderSelections>
      <ClaimsExchanges>
        <ClaimsExchange
          Id="LocalAccountSigninEmailExchange"
          TechnicalProfileReferenceId="SelfAsserted-LocalAccountSignin-Email" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 3 — Read user from directory (after sign-in completes) -->
    <!-- Skipped if objectId already populated from direct sign-up -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="3" Type="ClaimsExchange">
      <Preconditions>
        <Precondition Type="ClaimsExist" ExecuteActionsIf="true">
          <Value>objectId</Value>
          <Action>SkipThisOrchestrationStep</Action>
        </Precondition>
      </Preconditions>
      <ClaimsExchanges>
        <ClaimsExchange
          Id="AADUserReadWithObjectId"
          TechnicalProfileReferenceId="AAD-UserReadUsingObjectId" />
      </ClaimsExchanges>
    </OrchestrationStep>

    <!-- ─────────────────────────────────────────────────────────────────── -->
    <!-- STEP 4 — Issue the JWT token to the relying party -->
    <!-- ─────────────────────────────────────────────────────────────────── -->
    <OrchestrationStep Order="4" Type="SendClaims" CpimIssuerTechnicalProfileReferenceId="JwtIssuer" />

  </OrchestrationSteps>
</UserJourney>
4

Step 4 — Generate the authorization URLs in your application

With the policy in place, your application constructs two distinct authorization URLs — both pointing to the same RP policy, but the sign-up URL includes &action=signup as an extra parameter. MSAL automatically passes extra parameters through to B2C when you include them in the authorization request.

Application code — Authorization URLs for sign-in vs standalone sign-up (MSAL.js example)// Both links point to the SAME policy — only the extra parameter differs

// Sign-In link (standard — goes to combined page in sign-in mode)
// No ?action= parameter → clientActionIntent is empty → CombinedSignInAndSignUp runs
const signInRequest = {
  scopes: ["openid", "profile"],
  authority: "https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin"
  // No extra parameters needed for sign-in
};

// Sign-Up link (standalone — goes directly to registration form)
// ?action=signup → clientActionIntent = 'signup' → Step 1 (direct sign-up) runs
const signUpRequest = {
  scopes: ["openid", "profile"],
  authority: "https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin",
  extraQueryParameters: { action: "signup" } // This becomes ?action=signup in the auth URL
};

// Using MSAL.js — both call loginRedirect (or loginPopup) with the appropriate request
// Sign-In button: msalInstance.loginRedirect(signInRequest);
// Sign-Up button: msalInstance.loginRedirect(signUpRequest);

// Raw authorization URL structure (for non-MSAL integrations):
// Sign-In: https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/oauth2/v2.0/authorize
// ?p=B2C_1A_Signup_Signin&client_id=...&response_type=code&redirect_uri=...&scope=openid
// Sign-Up: same URL + &action=signup at the end
Figure 2 — How the orchestration step preconditions branch execution for each authorization URL
PATH A — Sign-In (no ?action= param)RP reads OAUTH-KV:action → clientActionIntent = (empty)Step 1 (Direct SignUp): SKIPPED→ ClaimsExist:clientActionIntent = false → SkipThisOrchestrationStepStep 2 (CombinedSignInAndSignUp): RUNS ✓→ objectId not in bag → precondition not triggered → step runsStep 3 (ReadUserFromDirectory): RUNS ✓Step 4 (SendClaims → JWT Token) ✓User sees combined sign-in/sign-up UISign-in tab is active by defaultPATH B — Direct Sign-Up (?action=signup)RP reads OAUTH-KV:action → clientActionIntent = 'signup'Step 1 (Direct SignUp): RUNS ✓→ claim exists + equals 'signup' → both preconditions satisfied → runsStep 2 (CombinedSignInAndSignUp): SKIPPED→ objectId now exists in bag (from Step 1) → SkipThisOrchestrationStepStep 3 (ReadUserFromDirectory): SKIPPED→ objectId exists → SkipThisOrchestrationStepStep 4 (SendClaims → JWT Token) ✓User sees sign-up registration form immediatelyNo combined page — direct registration UX
The objectId claim is the secondary guard — once a user completes sign-up in Step 1, objectId is in the claims bag. Steps 2 and 3 both check for it and skip automatically.
Adding Forgot Password via Sub-Journey

Forgot Password Sub-Journey — How It Fits In

Forgot Password works as an InvokeSubJourney orchestration step that is triggered when the user clicks "Forgot your password?" on the combined sign-in/sign-up page. In the B2C Identity Experience Framework, this click generates a special AADB2C90118 error code that your orchestration logic intercepts and routes to the sub-journey. This mechanism is independent of the clientActionIntent claim and works correctly without any additional modification to the branching logic above.

Add the Forgot Password sub-journey invocation as an additional orchestration step in your user journey. It sits between the combined step and the SendClaims step, and uses a precondition to skip unless the special forgot-password flag claim is set.

TrustFrameworkExtensions.xml — Adding Forgot Password as a sub-journey step<!-- This goes BEFORE the SendClaims step (Step 4 above becomes Step 5) -->
<!-- Add this claim declaration to ClaimsSchema first: -->
<!-- <ClaimType Id="isForgotPassword"><DataType>boolean</DataType></ClaimType> -->

<!-- Inside UserJourney — after Step 2 (CombinedSignInAndSignUp) -->

<OrchestrationStep Order="4" Type="InvokeSubJourney">
  <Preconditions>
    <!-- Only run the forgot-password sub-journey if isForgotPassword = true -->
    <!-- This claim is set when user clicks "Forgot your password?" on the combined page -->
    <Precondition Type="ClaimsExist" ExecuteActionsIf="false">
      <Value>isForgotPassword</Value>
      <Action>SkipThisOrchestrationStep</Action>
    </Precondition>
  </Preconditions>
  <JourneyList>
    <Candidate SubJourneyReferenceId="PasswordReset" />
  </JourneyList>
</OrchestrationStep>

<!-- The PasswordReset sub-journey handles OTP verification and password reset -->
<!-- It is defined separately as a <SubJourney Id="PasswordReset"> in the extensions file -->
<!-- After the sub-journey completes, execution returns to the parent journey -->
<!-- and continues to the SendClaims step (user is signed in after password reset) -->
Figure 3 — Complete policy file structure and what goes where
TrustFrameworkBase.xmlBuilt-in technical profiles:SelfAsserted-LocalAccountSignIn-EmailLocalAccountSignUpWithLogonEmailAAD-UserReadUsingObjectIdJwtIssuerDo not modifyTrustFrameworkExtensions.xml← Changes go here:ClaimsSchema:+ clientActionIntent (string)+ isForgotPassword (boolean)UserJourneys:+ Step 1 (Direct SignUp)with preconditions+ Step 4 (ForgotPasswordInvokeSubJourney)SubJourneys: PasswordResetB2C_1A_Signup_Signin.xml← Changes go here:RelyingParty:DefaultUserJourney:ReferenceId=SignUpOrSignInTechnicalProfile:InputClaims:+ clientActionIntentDefaultValue={OAUTH-KV:action}AlwaysUseDefault=true
Three changes total: one claim declaration in Extensions, one InputClaim in the RP file, and new orchestration steps in Extensions. TrustFrameworkBase.xml is never modified.
Testing and Debugging

Testing the Policy and Debugging with Application Insights

After uploading the updated policy files, test both paths using the "Run now" feature in the Azure portal Identity Experience Framework blade. For the direct sign-up path, add &action=signup to the "Run now" test URL.

Test URLs — Use these in the Identity Experience Framework "Run now" test page# Standard sign-in / combined page (no action parameter) https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin/oauth2/v2.0/authorize
  ?client_id=YOUR-CLIENT-ID
  &nonce=defaultNonce
  &redirect_uri=https://jwt.ms
  &scope=openid
  &response_type=id_token
  &prompt=login

# Direct sign-up (action=signup triggers Step 1) https://YOUR-TENANT.b2clogin.com/YOUR-TENANT.onmicrosoft.com/B2C_1A_Signup_Signin/oauth2/v2.0/authorize
  ?client_id=YOUR-CLIENT-ID
  &nonce=defaultNonce
  &redirect_uri=https://jwt.ms
  &scope=openid
  &response_type=id_token
  &prompt=login
  &action=signup <-- This is the key addition

# Debug with Application Insights trace logging enabled # Add &diags:{"applicationInsightsKey":"YOUR-AI-KEY"} to trace orchestration steps # Check Application Insights → Traces → filter by policy name → verify: # clientActionIntent claim value matches what was passed # Correct step is running / being skipped per the precondition logic
⚠ Common Mistakes and How to Avoid Them

CombinedSignInAndSignUp must not be Order 1 if you add a prior step. B2C historically required CombinedSignInAndSignUp to be the first orchestration step. Adding Step 1 (Direct SignUp) as Order 1 moves Combined to Order 2. The framework handles this correctly when the ClaimsProviderSelections reference a ClaimsExchange that exists in the combined step — but always test that the combined page still works correctly after reordering.

Do not include clientActionIntent in OutputClaims. This claim is internal routing logic. Including it in the RP's OutputClaims section would expose it in the JWT token returned to your application — this is unnecessary and may cause confusion. Keep it in InputClaims only.

AlwaysUseDefaultValue="true" is required. Without it, the OAUTH-KV resolver only populates the claim if the claim bag does not already contain a value for it. Since the claim bag starts empty for each request, this usually works — but AlwaysUseDefaultValue ensures correct behaviour regardless of claim bag state.

Handle the null/absent case in your preconditions. Use a ClaimsExist precondition before a ClaimEquals precondition on the same step. If the claim does not exist (no ?action= parameter was passed), evaluating a ClaimEquals on a non-existent claim can produce unexpected results in some policy versions. The two-precondition guard pattern in Step 1 above is the safe pattern.

Key Takeaways

A single Relying Party policy can serve sign-in, direct sign-up, and forgot password — no need for multiple RP files. The OAUTH-KV claim resolver and orchestration step preconditions do all the branching.
The OAUTH-KV claim resolver {OAUTH-KV:action} reads the ?action= query parameter from the OAuth 2.0 authorization request. It must be declared in InputClaims with AlwaysUseDefaultValue="true" in the RP TechnicalProfile.
The application's "Sign Up" button generates an authorization URL identical to "Sign In" but with &action=signup appended. Both URLs point to the same RP policy file and the same redirect_uri.
Step 1 (Direct Sign-Up) is skipped when clientActionIntent is absent or not equal to signup. Step 2 (Combined) is skipped when objectId is in the claims bag — which happens after Step 1 runs. These two guards together ensure only one path executes per request.
Forgot Password via sub-journey is unaffected by the clientActionIntent branching. It is triggered by the isForgotPassword claim set when the user clicks "Forgot password?" on the combined UI — an independent mechanism.
Use a two-precondition guard on Step 1: first check ClaimsExist, then check ClaimEquals. This prevents unexpected behaviour when the claim is absent and protects against null evaluation errors.
Test both paths using jwt.ms as the redirect URI. Add Application Insights trace logging to verify the claim value and confirm the correct orchestration steps are running and being skipped.
Frequently Asked Questions
Why not just use two separate RP policy files instead?
Two RP files is the alternative approach and is simpler to implement. The problem is policy sprawl — every change to business logic, claims schema, or technical profiles that applies to both flows must be made twice. In a production B2C tenant with compliance requirements, synchronized maintenance across multiple files is error-prone. The single RP with OAUTH-KV branching centralises all identity logic in one policy, which means one file to update, one file to review, and one file to audit. The operational benefit compounds over time as the policy evolves.
Is the ?action=signup parameter secure — can a malicious user modify it to bypass sign-in?
Yes, this parameter is secure for its intended purpose. The ?action=signup parameter only controls which UI screen is shown first. It does not bypass authentication — a user who navigates to the sign-up form still goes through the full registration process and receives a JWT token only after completing all validation steps. A malicious user could append ?action=signup to a sign-in URL, but this would only show them the registration form rather than the sign-in form — not a security bypass. The parameter controls UI flow, not authorization level.
Can I use a different parameter name instead of ?action=signup?
Yes. The parameter name and value are completely under your control. ?action=signup is a convention used in this guide, but you could equally use ?flow=register, ?mode=new-user, or any other convention. Whatever name you use in the URL must match the {OAUTH-KV:name} resolver syntax in the policy, and whatever value you use must match the ClaimEquals precondition value. The claim type name (clientActionIntent) is also just a convention — rename it to anything that makes sense in your policy context.
What if I also want to support social identity providers (Google, Facebook) on the combined page?
The branching logic for the direct sign-up path is independent of social identity provider support on the combined page. Social IdP buttons are configured as ClaimsProviderSelections in the CombinedSignInAndSignUp step (Step 2 in this guide). They continue to work as normal when no ?action=signup parameter is present. For the direct sign-up path (Step 1), you can optionally add a separate step that presents social IdP options during registration, or you can keep the direct sign-up path as local account only. The choice depends on whether your direct sign-up link should support social registration or only email/password registration.
I'm seeing the combined page even when I pass ?action=signup — what is wrong?
The most common causes: (1) AlwaysUseDefaultValue="true" is missing from the InputClaim in the RP file — without it the resolver may not populate the claim consistently. (2) The claim type clientActionIntent is not declared in the ClaimsSchema — if the claim type does not exist, the resolver cannot map to it. (3) The preconditions on Step 1 have ExecuteActionsIf set incorrectly — double-check the logic: you want to skip Step 1 if the claim does not exist (ClaimsExist ExecuteActionsIf="false") and also skip it if the claim exists but is not equal to signup (ClaimEquals ExecuteActionsIf="false"). Use Application Insights trace logging to confirm the claim value is being read correctly before checking precondition logic.

Popular posts from this blog

The Cloud Incumbent: AWS Bedrock Hosts Every Frontier Model and Amazon Is Betting on Neutrality AWS at $37.6 billion quarterly revenue, growing 28%. $13 billion invested in Anthropic. A $100 billion Anthropic-to-AWS commitment. Trainium with $225 billion in customer revenue commitments. The most quietly powerful AI strategy in the race. By Francis Avorgbedor | Azure Engineer  ·  July 4, 2026  ·  14 min read  ·  Amazon · AWS · Cloud AI 74 SEVENAI Momentum Score — Rank #5 $37.6B AWS Q1 2026 revenue — 28% YoY growth ▲ Fastest in 15 quarters $13B Total Amazon investment in Anthropic to date ▲ Strategic anchor 100K+ Customers running Claude on AWS Bedrock ▲ Distribution moat Amazon's AI strategy is built on a thesis that every other Magnificent Seven company is testing against — and that Amazon is uniquely positioned to win regardless of the outcome. The thesis is neutrality. In a race where Microsoft has bet on OpenAI, Google has bet on Gemini, and Meta has bet...
Performance Fix Foundry Local 1.2 Linux ARM64 Embeddings Offline ASR The Edge Latency Drop: Fixing Latency Spikes by Offloading Embeddings to Foundry Local 1.2 You are paying a full cloud round trip — network, TLS, queue, throttle risk — to turn a twelve-word search query into a vector. That is the most expensive way possible to do one of the cheapest computations in your stack. Foundry Local 1.2 now runs on Linux ARM64, which means embeddings and speech recognition can happen on a Raspberry Pi, a Jetson, or a Graviton instance — offline, unmetered, and in single-digit milliseconds. The failure signature this guide resolves # Application Insights — the embedding call, not the LLM, is your tail latency: name p50 p95 p99 calls/day POST /embeddings (cloud) 89 ms 412 ms 3,847 ms 1,240,000 POST /chat/completions (cloud) 940 ms 1,720 ms 2,910 ms 38,000 ^^^^^^^^ ...
  The 500GB System File That Eats Your Hard Drive Something on your Windows 10 drive is consuming hundreds of gigabytes and the normal tools cannot find it. This guide identifies every known culprit — from hibernation files and shadow copies to runaway backups and the Windows component store — and tells you exactly what is safe to delete, what to leave alone, and what the commands actually do.
How to Reset an Azure Virtual Machine to Factory Settings Using a Managed Disk Azure does not have a single "factory reset" button. What it does have is something better: the OS Disk Swap — a method that swaps out the corrupted or misconfigured OS disk for a clean Windows Server managed disk without deleting the VM, its NICs, its IP addresses, or any attached data disks. Here is how it works, when to use it, and the exact steps to execute it safely. FA Francis Avorgbedor Azure Engineer July 16, 2026 15 min read Azure VMs · Windows Server · Real-World Fix 3 Methods to achieve a clean Windows Server installation on an existing Azure VM ~15min Typical OS Disk Swap duration — VM retains its NICs, IPs, and data disks throughout 0 Data disks affected by an OS Disk Swap — data disks remain attached and untouched 1 Snapshot of the original OS disk you must take before starting — no exceptions Introduction Why Azure Does Not Have a Simple Factory Reset — and What to Do Instead On a ph...

AKS CrashLoopBackOff, Pending Pods, and NotReady Nodes — The Real Fixes Engineers Use

Incident Playbook AKS Kubernetes kubectl 2026 AKS CrashLoopBackOff, Pending Pods, and NotReady Nodes — The Real Fixes Engineers Use Every AKS engineer eventually faces the same nightmare: CrashLoopBackOff at 2am, pods stuck Pending for no clear reason, or nodes flipping to NotReady mid-deployment. The difference between panic and control is knowing the exact diagnostic sequence — and the real fixes that work in production. This guide gives you both. 3 commands get pods, describe pod, and logs diagnose roughly 90% of AKS incidents before you touch anything else Exit 137 The code that means OOMKilled — the container hit its memory limit and was killed by the kernel (128 + SIGKILL 9) Events The bottom of kubectl describe is where the real cause lives — Pending, FailedScheduling, and image errors all surface there CoreDNS The single component behind most "intermittent" production failures — service discovery breaks quietly and looks like an app bug Table of Contents 01 The 3 Comm...
Can I Update My Old Computer to Windows 11 — and How Much Will It Cost? Your i7, 16GB RAM, 512GB SSD machine is powerful enough to run Windows 11 comfortably. The TPM 2.0 and Secure Boot wall is a security checkbox, not a performance ceiling. Here are two proven ways to get past it, what each one costs, and what you are trading away by doing so. $0 Cost of the Windows 11 licence if your existing Windows 10 is genuine — the upgrade remains free in 2026 2 Proven methods to bypass TPM 2.0 and Secure Boot — Rufus (easy) and Registry edit (manual) 25H2 Current Windows 11 version — all known bypass methods tested and confirmed working as of July 2026 Oct 2025 Windows 10 end of life — no more security updates. Staying on Windows 10 now carries real risk. First — Check Your BIOS Before Anything Else You Might Not Actually Need a Bypass Before running any bypass, open your BIOS and look at two settings. Many computers that fail the Windows 11 compatibility check have TPM 2.0 present in the hard...
2026 Edition 100 Tools Software Engineering DevOps AIOps Top 100 Best AI Tools for Azure  Engineers and DevOps Professionals in 2026 85% of developers now regularly use AI tools. Fully AI-generated code accounts for nearly 28% of all pull requests. The question is no longer whether to use AI tools — it is which ones, in which combination, for which part of the lifecycle. This guide cuts through the noise: 100 tools, 10 categories, honest pricing, real use cases, and a selection framework for building your stack without redundancy. 85% Percentage of developers who now regularly use AI tools, per JetBrains' 2025 State of Developer Ecosystem report — up from near zero three years ago 28% Share of all pull requests containing primarily AI-generated code in 2026 — the metric that signals AI coding assistants have moved from experiment to workflow $50B Cursor's reported valuation in April 2026 Series D talks — the number that signals investor confidence in the AI developer tools mark...

Azure Files vs Azure NetApp Files: Which One Should You Choose?

Azure Files vs Azure NetApp Files: Which One Should You Choose? Performance tiers, protocol support, dual-protocol capability, pricing models, SAP/Oracle/HPC suitability, data management features, and the decision framework that maps each workload type to the right service — with step-by-step setup procedures for both. FA Francis Avorgbedor Azure Engineer July 15, 2026 20 min read Azure Storage · Architecture 4 Azure Files tiers: Premium SSD, Standard Hot, Cool, Tx Optimized 3 ANF performance tiers: Standard, Premium, Ultra — all SSD-backed 4TiB ANF minimum provisioning — significant cost floor for small workloads Dual ANF serves the same data via SMB and NFS simultaneously — AF cannot Introduction Two Services, One Surface Area — Completely Different Purposes Microsoft offers two fully managed, enterprise-grade file storage services in Azure. They share a surface area — both serve file shares over standard protocols, both run on managed infrastructure, and both integrate with Microsof...
Troubleshooting Guide AKS Kubernetes Real Solutions kubectl Azure Kubernetes Service (AKS) Troubleshooting Guide: Real Solutions to Common Problems CrashLoopBackOff at 2am. Pods stuck Pending with no obvious cause. Nodes going NotReady mid-deployment. DNS resolution silently failing in production. Every AKS engineer encounters these — the difference between engineers who panic and engineers who stay calm is knowing the exact sequence of diagnostic commands to run. This guide gives you that sequence, the root cause analysis for each failure mode, and the fix. 3 commands 90% of AKS problems are diagnosed with the same three kubectl commands: describe pod, logs --previous, and get events — in that order, every time Exit 137 The exit code that tells you everything: container killed by SIGKILL — either the Linux OOM killer (memory limit exceeded) or kubelet after grace period expired 5 min The CrashLoopBackOff ceiling: Kubernetes applies exponential backoff (10s → 20s → 40s → 80s → 160s → 3...

How to Deploy an AI Chatbot on Azure Using Azure OpenAI and App Service

Step-by-Step Guide Azure OpenAI App Service Production Python How to Deploy an AI Chatbot on Azure Using Azure OpenAI and App Service From zero to a production-grade AI chatbot: provision Azure OpenAI, write a streaming Flask API backend, deploy it on Azure App Service with Managed Identity, wire in conversation history and content safety, and instrument it with Application Insights — all with complete code and Terraform IaC. No API keys in environment variables. No hardcoded secrets. No half-finished PoC patterns. 7 phases This guide covers the full deployment lifecycle: architecture design → resource provisioning → backend code → App Service deployment → streaming → security → monitoring Zero keys The chatbot authenticates to Azure OpenAI using Managed Identity and DefaultAzureCredential — no API keys stored in environment variables, Key Vault, or code SSE Server-Sent Events stream GPT tokens to the browser as they generate — the same token-by-token typing effect users expect from pr...