feature_image (3)

Managing APIM policies at scale: a practical guide to Azure APIM policy fragments

It is Thursday afternoon when a security architect joins the platform call with a relatively straightforward request: from the following week, every externally exposed API needs to validate a new client-type claim in the access token.

Azure API Management (APIM) is a Microsoft Azure service that helps organisations publish, secure and manage APIs at scale. It acts as a managed gateway between an organisation’s APIs and the people, applications or systems that use them.

From an APIM perspective, the policy change itself is simple. APIM already provides the capability to validate JWTs and required claims.

The more interesting question is:

Where does that change need to be applied?

The API platform began two years earlier with six APIs. It now supports more than 50 APIs across customer, partner and internal domains, with separate DEV, TEST and PROD environments. Over time, the policy estate has evolved with the platform.

Some authentication policies sit at API scope. A few have been applied to individual operations. Other variations exist at product scope. Most policy changes are deployed through source control, although a handful of production fixes have also been applied directly through APIM.

A review identifies more than two dozen implementations of JWT validation. Some are identical, some vary only by audience and others contain genuine behavioural differences.

The real challenge is that nobody can immediately confirm which variations are intentional. At this point, APIM policy management becomes less about writing XML and more about platform design and operational consistency.

The question changes from:

“How do we implement an APIM policy?”

to:

“How do we manage reusable behaviour, API-specific requirements, configuration, policy scope and change impact across the estate?”

This is where Azure API Management Policy Fragments become useful.

A policy fragment is a centrally managed, reusable collection of APIM policy statements referenced using include-fragment. In a larger APIM environment, its value goes beyond reducing duplicated XML.

The more useful design discussion is:

Which behaviours represent reusable platform capabilities, and where do those capabilities belong?

When policy duplication starts to affect maintainability

The original implementation may have been entirely reasonable. With six APIs, copying a small policy is often the quickest way to move forward.

For example:

<validate-jwt header-name="Authorization"
              failed-validation-httpcode="401">
    <openid-config url="{{identity-openid-config}}" />
    <audiences>
        <audience>api://orders</audience>
    </audiences>
</validate-jwt>

The Payments API arrives and requires similar authentication. The policy is copied.

A partner API follows, with slightly different claims. Another variation is introduced.

As the platform grows, the same pattern begins appearing across authentication, correlation IDs, request logging, headers, rate limiting, backend routing and error handling. None of those individual decisions necessarily creates a problem. The challenge appears when the team needs to change a shared behaviour across many APIs.

At that point, policy differences create questions:

  • Which versions are still current?

  • Which differences are intentional?

  • Which APIs rely on a specific variation?

  • How consistently is the policy represented across environments?

For a larger estate, a practical design principle is to identify stable capabilities that benefit from central ownership, rather than creating a fragment simply because two pieces of XML look similar.

For example:

  • security-customer-jwt

  • security-partner-jwt

  • observability-correlation

  • observability-request-logging

  • traffic-partner-rate-limit

  • response-security-headers

There is an important nuance here.

Customer authentication and partner authentication may use similar policy statements while representing different security models. Trying to bring every JWT scenario into a single universal fragment can make the fragment increasingly conditional and difficult to reason about. A more sustainable pattern is:

Reuse behaviour that is genuinely stable and shared.

Step 1: Separate reusable behaviour from API-specific context

Assume the customer-facing APIs share the same authentication approach. A reusable fragment might be introduced as:

security-customer-jwt

The Orders API can then establish the information that is specific to Orders before invoking the common fragment:

<inbound>
    <base />
    <set-variable name="expected-audience"
                  value="api://orders" />
    <include-fragment
        fragment-id="security-customer-jwt" />
</inbound>

This distinction is particularly important in larger APIM environments.

The Orders API may expect:

api://orders

while Payments expects:

api://payments

and Customer Services expects another audience.

These values are API-specific, even though all three APIs may share the same authentication behaviour. The API policy therefore establishes the API-specific context, while the fragment provides the reusable security capability.

Inside the fragment, that value can be retrieved from context, for example:

@(context.Variables.GetValueOrDefault<string>
    ("expected-audience", ""))

This gives us a useful separation:

  • Policy Fragment → reusable behaviour

  • API Policy → API-specific context

  • Named Values → environment-specific configuration

 

That boundary becomes increasingly valuable as the API estate grows.

Step 2: Keep environment configuration separate

Now consider values that genuinely differ between environments.

Development might authenticate against:

https://identity-dev.contoso.com

while production uses:

https://identity.contoso.com

This is different from the API audience example. The identity endpoint is an environment concern. A practical pattern is to use the same Named Value key in each APIM environment:

identity-openid-config

with different values behind it:

  • DEV → development identity endpoint

  • TEST → test identity endpoint

  • PROD → production identity endpoint

The fragment remains consistent. The API provides API-specific context. The environment provides deployment-specific configuration. This separation gives the delivery model a much cleaner shape: one reusable policy definition, deployed across DEV, TEST and PROD, with configuration supplied by each environment.

The same approach can apply to telemetry destinations, backend identifiers and other values that vary between environments. This is often one of the most useful design discussions because it reduces the temptation to maintain separate copies of the same policy simply to accommodate environment differences.

Step 3: Place behaviour at the scope where it naturally belongs

Once reusable fragments exist, the next question is where they are referenced. APIM supports policy composition across global, product, API and operation scopes. Workspaces also introduce another organisational boundary for modern federated APIM models.

A useful way to think about the scopes is:

GLOBAL 

  | 

  └── gateway-wide behaviour 

 

PRODUCT / WORKSPACE 

  | 

  └── consumer or domain behaviour 

 

API 

  | 

  └── API-wide behaviour 

 

OPERATION 

  | 

  └── operation-specific behaviour 

The objective is not simply to place reusable behaviour at the highest available scope.

The more useful question is:

At which scope does this behaviour naturally belong, and under which request paths is its execution predictable?

Consider partner rate limiting. Applying a shared rate-limiting fragment at Partner Product scope can be a good fit where the subscription model aligns with that product.

There is, however, an APIM detail worth recognising: product-level policies are not applied to every subscription model. API-scoped subscriptions and all-APIs subscriptions can follow different paths. For controls that form part of a security or traffic-management boundary, the scope therefore benefits from being considered alongside the subscription model. This is less about finding one universally correct scope and more about understanding how traffic reaches the API.

Step 4: Treat policy inheritance as part of the execution design

Treat <base /> as part of the execution design.

Consider this API policy:

<inbound>
    <base />
    <include-fragment
        fragment-id="security-customer-jwt" />
    <include-fragment
        fragment-id="observability-correlation" />
</inbound>

<base /> is easy to overlook when reviewing APIM policies.

In practice, it plays an important role.

It means:

Include the policy from the next broader scope at this point in the current policy.

As a result, placement affects execution order.

For example:

<base />
<include-fragment fragment-id="security-customer-jwt" />

and:

<include-fragment fragment-id="security-customer-jwt" />
<base />

represent different execution sequences. That difference may become relevant when policies rely on authentication context, transformed headers, variables or routing information established earlier in the pipeline. When reviewing a fragment-based design, one of the useful questions is therefore:

What behaviour is expected to have run before this fragment executes?

That question often reveals more about the design than looking at the fragment in isolation.

Step 5: A policy fragment is not quite the same as a function

Developers familiar with application code may initially view a fragment as something similar to:

validateJwt(audience, issuer, claims)

The model in APIM is different. Fragments do not expose a conventional typed parameter contract. Reusable policies commonly work with APIM context, Named Values and context variables created earlier in the policy pipeline.

For example, an observability fragment may expect values such as:

  • correlation-id

  • authenticated-client

  • selected-backend

to already be available.

This introduces an important design consideration. Policy fragments reduce duplicated XML, while dependencies between fragments may still exist through execution order and shared context. For larger implementations, it is useful to make those dependencies visible and keep fragment responsibilities focused.

Defensive access patterns such as GetValueOrDefault can also make fragment interaction easier to manage when optional values are involved.

The goal is not simply modular XML. It is predictable composition.

Step 6: Consider reuse and blast radius together

Return to our original security fragment:

security-customer-jwt

Imagine it is now referenced by 30 APIs.

That gives the team significant leverage. One implementation represents authentication behaviour across a large part of the estate. The same centralisation also means that a change to the fragment may affect all 30 consumers.

This does not make reuse undesirable. It simply changes the way the team approaches change management.

A practical workflow becomes:

APIM also provides management capabilities for identifying references to a policy fragment, which can help teams understand where a shared fragment is being consumed. This is an important distinction:

Centralisation reduces duplicated implementation effort; it does not reduce the value of impact analysis and testing.

In fact, the wider the reuse, the more useful that visibility becomes.

Six months later, the conversation is different

The identity team returns with another authentication change. This time the platform team does not begin by searching through dozens of policies. Instead, the conversation becomes:

Which capability owns customer authentication?

security-customer-jwt

Which APIs reference it?

That can be identified before deployment.

Which values vary by API?

Those are represented through API-specific context.

Which values vary by environment?

Those are represented through environment configuration.

Where does the behaviour execute?

That is visible through the policy scopes and <base /> placement.

How broadly will the change be felt?

The fragment references provide the starting point for impact analysis. The XML is not necessarily the most important improvement.

The real improvement is that the platform has become easier to reason about.

Policy fragments are one part of the operating model

It is tempting to summarise the journey as:

In practice, mature APIM environments tend to involve a few more design decisions:

Policy fragments provide an effective mechanism within that model. Used selectively, they give authentication, observability, traffic management and other reusable platform capabilities a clear place to live. APIs can then compose those capabilities according to their requirements rather than maintain independent copies of the same policy logic. This brings us back to the Thursday afternoon request.

The interesting question was never whether APIM can validate another JWT claim.

It can. The more valuable question for the platform team is:

“If we change this behaviour once, can we clearly identify where it executes, what it depends on, which APIs consume it and how that change moves through our environments?”

When those answers are visible, APIM policy management becomes considerably more predictable. That is where policy fragments provide their real value: not simply as a way to reuse XML, but as part of a structured approach to managing Azure API Management at scale.

Get started on the right path to cloud success today. Our Crew are standing by to answer your questions and get you up and running.