Alternate Access Mappings (AAMs) *Explained

Based on many of the support cases that I've seen, Alternate Access Mappings (AAM) may be one of the least understood aspects of SharePoint and can have substantial impact on Search (both Crawl and Query). In this post, I'll document some of my experiences and insights on AAMs.

Note:  "Plan alternate access mappings (Office SharePoint Server)" is the best resource I've found for documenting AAMs, which covers both several configuration scenarios and troubleshooting common mistakes. Although listed as SharePoint 2007 content, its information largely applies to both SharePoint 2010 and SharePoint 2013. I won't duplicate that TechNet page, but I will make reference (calling it the "Plan for AAMs" document) to reiterate some aspects that have particular impact for Search.

Updates: I recommend also reading my follow on post here that further dives into the problems that occur when crawling the non-default zone and work to show why crawling the default zone should be considered required (*hint: it's going to break otherwise). I also have a redux post here on AAMs that provides even more illustrations to explain this.

The most common mistakes I see regarding AAMs tend to fall into the following groups (more detail on each of these throughout this post):

  • Crawling the non-Default zone URL for the Web Application 
  • Creating a new AAM zone without extending the Web Application or manually altering the Public URL of any zone from Central Admin
    • This can cause ambiguous scenarios for routing requests to SharePoint and result in connectivity issues or unexpected authentication failures
    • Unless configuring for Reverse Proxy or adding additional Internal address (both fairly uncommon), there's almost no reason to manually alter AAMs
  • Assuming that updates made in AAMs automatically update IIS bindings (Source: Plan for AAMs)
    • A by-product of this: If IIS host name bindings are generic across multiple IIS Sites and AAMs are modified incorrectly, a single w3wp.exe process may be incorrectly handling requests for another SharePoint Web Application
  • Not configuring External Resource Mappings in the Search Farm when crawling another farm 


AAMs: An Overview and Base Example

In the Plan for AAMs document (referenced above), it provides the following description (again, this also applies to SP2010 and SP2013):

"Alternate access mappings enable a Web application that receives a request for an internal URL, in one of the five authentication zones, to return pages that contain links to the public URL for the zone. You can associate a Web application with a collection of mappings between internal and public URLs. Internal refers to the URL of a Web request as it is received by Office SharePoint Server 2007. Public refers to the URL of an externally accessible Web site. The public URL is the base URL that Office SharePoint Server 2007 uses in the pages that it returns. If the internal URL has been modified by a reverse proxy device, it can differ from the public URL."

That accurately describes it, but if you've never seen it defined before, it's easy to get hung up on the difference between the Internal URL versus the Public URL or some other nuance of this. Or if you're like me... you made it about fifteen words into that before your eyes glazed and you started skimming it. So, let me try to describe this with pictures (which you can click on these to see a bigger view).

First, assume you just created a Web Application with a load balanced URL https://initech and haven't configured any other modifications to the AAMs. For this, your AAMs would resemble the following:

And the communication flow for a page request from the user would look something like this...

Now, let's look at some definitions to help you get your mind wrapped around Internal and Public URLs:

  • Internal URL:  It would probably  make more sense if this were named with the OM property "Incoming URL", because (I can't find an "official" definition, but) the Internal URL essentially defines the URL(s) that SharePoint deems as viable requests coming into SharePoint (It's important to distinguish this from the bindings at the IIS level, which occur before the request gets to SharePoint). In this example above, the Internal URL is represented by the "HTTP GET (https://initech)" arrow coming from the client. As an analogy, if you called me "Brian" or "bspender", I'd answer you. However, if you called me "Todd", I might not realize you were talking to me.
  • Public URL: After a request is received by SharePoint, a page is built by the server and returned to the client. In this page, there are links to other content (think menus, web parts, and so on), and these links are all relative to the current URL. For example, if you're visiting https://initech, all of these links in this page would be relative to https://initech (think: https://initech/path/page.aspx). If you had multiple AAMs configured, you may be accessing this same page as https://foo/path/page.aspx where all of its links would then be relative to https://foo as in the example below. The Public URL is essentially the root to all of these relative URLs (e.g. https://initech or https://foo )... it defines with which URL root each anchor tag will be stamped when the page is built by the server and returned to the requesting client. Below demonstrates the same page being loaded from two different URL zones. In this, the structure of the page is the same, but the URLs in each anchor tag have a different root:


Typically, the Internal URL is the same as the Public URL, so it's not always obvious that there is a difference between the two. But what if you added a second Internal URL, such as:

Adding a second internal address is common when you want to target a specific server rather than a load balanced address. In both cases, the user is targeting the same SharePoint Web Application (and more specifically, the same Web Application Zone), but via a different "incoming" URL.

In this scenario of browsing to https://someServer, the picture would look exactly as the communication flow depiction above, except the initial request from the client would contain "HTTP GET (https://someServer)". Even so, the rendered page would still show relative to its Public URL, https://initech. In other words, if the user browsed to https://someServer, it would pull the same content as when browsing to https://initech. However, when browsing to https://someServer, the URL in my address bar would change back to https://initech (the Public URL) such as:

Note: Technically, this isn't redirecting to https://initech, but the page will display relative to https://initech. However, the page has to then pull back JavaScript, CSS files, images and other resources to full load the page content. The links to these resources are defined server-side as relative URLs...using the Public URL for this request. Thus, the page loads with references to the load balanced address https://initech and will pull these resources from https://initech.

This is common a strategy for troubleshooting/targeting a specific web server to process a request. Think https://your.typical.load.balanced.url (which would  route through a NLB) versus the same request targeted to a specific server such as https://server1 or https://server2 etc...). It is also required when setting Web App's SiteDataServers property for implementing dedicated crawl targets. 


Extending the Web Application and Why It's Important

In a second example, the Web Application gets extended into another zone, such as:


Which would have a corresponding communication flow like:

In this, the same content is rendered via different URLs, where each URL represents a different zone (and in this case, each zone also has a different Authentication Provider, but it is not required to be different). A common problem occurs when creating a new AAM zone without extending the Web Application (or similarly, manually altering the Public URL of any zone from Central Admin). To better describe why this causes a problem, I need to first provide some background.

When creating a Web Application, SharePoint also creates a corresponding IIS Site (an IIS Site is different than a SharePoint Site [which is really a Site Collection] or a SharePoint Web [which is often called the root or sub-site]... unfortunately, the term "site" is often used interchangeably causing a ton of confusion). When a request reaches a server, the underlying server subsystems (such as HTTP.SYS) route these to IIS. Using the IIS Sites and its bindings, these requests are then routed to the appropriate w3wp.exe for processing (in other words, an IIS Site is bound to a particular App Pool, which has a w3wp.exe process).

Note: Check out SharePoint as an ASP.NET-IIS Application for much more information on this topic, which includes the following:

"A web application in SharePoint terminology is closely related to what is called a website in IIS terminology...  It can be helpful, especially when you are trying to see the relation between SharePoint and IIS from a high and broad perspective, to think of the SharePoint web application and its corresponding IIS website as a single entity...  [A]lthough there is usually a one-to-one relation between SharePoint web applications and IIS websites, this is not always the case."

When extending a Web Application into another zone, SharePoint:

  1. Creates a new IIS Site to represent this extended zone (which uses the same App Pool as the default zone, meaning the same w3sp.exe process for each Web Application zone)
    • Because IIS Bindings are set at the IIS Site, this has significant implications on how requests get routed to the appropriate SharePoint Web Application
    • The web.config also lives within the IIS Site, which should be of consideration if this zone has different Authentication Providers [per zone] and/or customizations
  2. Modifies the Alternate Access Mappings to include the new zone

When just simply modifying the AAMs without extending the Web Application, the IIS Site does not get created for the extended zone. In fact, from PowerShell, we can verify that the IisSettings object does not created for the Web Application. For example, in my Farm, I manually created an Intranet zone by simply adding a new AAM rather than extending the Web Application, then ran the following:

$webApp = Get-SPWebApplication https://initech
    ServerComment : SharePoint Initech 80
    Path : C:\inetpub\wwwroot\wss\VirtualDirectories\initech80
    ServerBindings : {Microsoft.SharePoint.Administration.SPServerBinding}
    #...this is empty because IisSettings is $null

The Plan for AAMs also notes the following (and I wish this were also explicitly documented for SP2010 and SP2013, but this article was never updated for these newer versions. In either case, this functionality hasn't really changed across the versions, so it - in my mind- applies to all version of SharePoint):

"We recommend extending a Web application to a new IIS Web site for each zone you want to use. This provides a backing IIS Web site. We do not recommend reusing the same IIS Web site for multiple zones, unless you are specifically told to do so by Microsoft. "

Depending on the bindings in the other IIS Sites (particularly with "*" [wildcard] host headers and/or multiple sites using the same port), it is quite possible to create ambiguous scenarios where requests may reach the incorrect w3wp.exe for processing (here is a Microsoft KB and here is another blog describing this behavior). In this scenario, SharePoint can in cases still accept the request and process it. Here, it is quite possible that things will appear to work, but it might also create some weird idiosyncrasies that can't be fully explained.

  • For the customers that I've had with these types of problems, the was generally resolved by detaching the Content DB(s), rebuilding the Web Application, and then extending the Web App into the additional zones.

A similar problem occurs when manually altering the AAMs from Central Admin (e.g. changing the AAMs without extending). This, as noted as "Mistake 4" in the Plan for AAMs TechNet, seems to correlate to a common misconception that "updates made in alternate access mappings automatically update IIS bindings". However, changes to AAMs are not reflected in IIS (whereas extending the Web Application creates a new IIS Site with the appropriate IIS settings/bindings in place). Thus, manually changing the AAMs could induce these problems even if the zones were originally extended.


Some Impacts to Crawling the non-Default URL

This isn't documented anywhere, but I'm convinced that there is an inherent assumption built into SharePoint that a Web Application's Default zone will be crawled (specifically, the Public URL).

For example, in SharePoint 2010, contextual scopes and popular social tags both break if crawling the non-Default zone (Contextual scopes break because the query processor attempts to translate the URL to the Default zone's Public URL before processing the query. For Social Tags, SharePoint normalizes the tagged target URL to its Default zone's Public URL before storing it in the Social DB).

In SharePoint 2013, URL-related managed properties including Path, ParentURL and SPSiteUrl all store values relative to the URL that was crawled. However, as demonstrated in my previous post, these clearly get negatively impacted at query time by crawling the non-Default zone (again because the query processor attempts to translate the URL to the Default zone's Public URL before processing the query).

  • It is possible in these cases that queries may seem to function properly from one zone, but not another (and things may be misbehaving from all zones)
  • If crawling the non-Default zone, change the Search Content source to specify the Default URL and start a full crawl
    • Note: Don't just simply add the Default URL... replace one URL for the other (in other words, you should not be crawling the same Web Application using multiple URLs)

Also, although not directly caused by AAM configuration, AAMs do play a contributing role on the configuration of IIS Bindings, DNS (or HOSTS files), load balancers, proxy servers, and the DisableLoopbackCheck (or BackConnectionHostNames) registry settings.


Mapping External Resources

As noted above, some query-time scenarios require a translation between zones using the AAMs. However, AAMs are an aspect of Web Applications, so what happens if the Web Application is in a remote farm (e.g. as in a Enterprise Services Publishing/Consuming scenario where the Search Farm is different than the content Farm)? For this, we have the ability to create an "External Resource Mapping" in the Search Farm. These allow you to create AAMs for an external Farm within the local Search Farm. In this blog, the author describes this scenario and shows how to build the External Resource Mappings.

Essentially, you're duplicating the alternate access mappings in the Search Farm so the query processor can properly map the requests to the correct Default zone. For example, if the original Web App in the content farm has a Default, Intranet, and Extranet mapping, you'd want to create an External Resource Mapping in the Search farm and provide the URLs for the target's Default, Intranet, and Extranet zones.