Last June at TechEd North America, I presented a talk on best practices for Group Policy design with performance and security in mind. This article is based on that talk. In it, I hope to provide you with some guidance and best practices on what makes good Group Policy design.

What Is a Good Group Policy Design?

Before you can aim for a best practice, you need to have some idea of your target. In the context of Group Policy, what are good design criteria? I typically shoot for achieving a balance of the following elements:

  • Minimal impact to the end user
  • Balance of security and lockdown goals
  • Minimal management overhead and complexity

The challenge in all of this is that sometimes these three goals work at cross purposes to one another. For example, having a minimal impact on the end user while also meeting your organization's security goals might be difficult.

When I first started using Group Policy (and even its predecessor, System Policy in Windows NT 4.0), I had a tendency to take the newfound power I'd gained with these technologies and tweak as many switches as possible. Over the years, I've learned that more is not necessarily better when it comes to Group Policy. That's why it's also important to know your business needs before you embark on tightening the proverbial policy screws.

Another key question that I'll dive in to is how many Group Policy Objects (GPOs) are too many. And once again, I take the "Goldilocks" approach to this question -- just enough GPOs and just enough complexity to accommodate the needs of the business yields a design that's just right.

OK, enough about the "soft" side of Group Policy design. Let's talk nuts and bolts!

Monolithic vs. Functional GPOs

One decision you'll need to make as you deploy GPOs in your environment is how you'll group settings within those GPOs. I use the terms monolithic and functional to describe the two possible approaches:

  • Monolithic GPOs -- Contain a variety of settings from multiple policy areas (e.g., Administrative Templates, security, Group Policy preferences)
  • Functional GPOs -- Contain one or more settings from a single policy area and often target a single function (e.g., Internet Explorer -- IE -- lockdown)

Most environments have a mix of both types of GPOs -- driven by factors such as the need for delegating certain GPOs to a particular business unit administrator, the desire to manage complexity, and the need to enforce security mandates. A perfect example of a functional GPO is one that contains domainwide security policies. In that situation, you might have one functional GPO that sets those domainwide policies and can be edited by only one person or group (e.g., the security operations group).

The goal of the functional GPO is to isolate one or more settings from a single policy area so that they can be handled as a unit and easily delegated to a particular user or group if need be. However, you can go overboard with functional GPOs. Having 100 GPOs, each with a single setting, is a tangible example. There are performance penalties to be paid if you have many, many GPOs, though those penalties might not be as bad as you'd expect.

The goal of monolithic GPOs is to bundle together a complete configuration scenario within one GPO. Be it the Marketing Desktop Lockdown GPO or the Mobile User Configuration GPO, the goal is to keep all settings that relate to the scenario in one manageable and delegated GPO. Monolithic GPOs are ideal for the organizational unit (OU) administrator who needs to have control over Group Policy settings for users but shouldn't be able to create GPOs willy-nilly. Monolithic GPOs also ease troubleshooting: Because one GPO is responsible for the lion's share of policy, you have only one place to look when something goes awry.

The bottom line is that monolithic or functional GPOs both make sense in certain situations, but one might be better than the other from a Group Policy processing-performance perspective. More on that later.

Linking vs. Filtering

The question of where to link your GPOs and when to use filtering on them is another decision that has both complexity and performance ramifications for your GPO design. You're faced with two choices:

  • Link GPOs as close to the intended target as possible.
  • Link GPOs higher in the Active Directory (AD) hierarchy, and then rely on filtering (e.g., security groups, Windows Management Instrumentation -- WMI -- filters, Group Policy preferences item-level targeting) to get the setting where it needs to go.

You'll find reasons to support both choices. Much of the decision will depend on your AD design (which I'll talk about in the next section). My guiding principle is that you should always seek to link a GPO as close to the intended targets as possible and rely on filtering on an exception basis only. This is easier said than done when you have a flat AD hierarchy (i.e., all users in one OU). But if you can adhere to this principle, you not only reduce complexity in your environment, you also take away the performance impact of needing clients to evaluate a variety of filters on a given GPO to determine whether it applies. And if you throw in the use of Group Policy preferences item-level targeting, which lets you create filters on individual settings, well . . . it's easy to see how things can get out of hand. Pretty soon, your clients are evaluating tens of filters just to determine whether a given GPO applies to them, let alone processing GPO settings. The performance impact can be even more profound if you're using item-level targets that require network communication to resolve. Examples of these targeting items include Security Group, LDAP Query, Domain, Site, and Organizational Unit, all of which require LDAP calls to AD.

Again, using linking as the primary mechanism for targeting GPOs is a good practice. Filtering is definitely a valuable feature of Group Policy and Group Policy preferences, but be aware of the possible performance and complexity penalties that you can pay if you rely too heavily on those targeting tools.

Balancing Active Directory and Group Policy Design

When it comes to how your AD design interacts with your Group Policy design, finding common ground is often a struggle. AD designs tend to be driven by criteria such as application requirements, delegation, and administration. Group Policy is driven by targeting convenience, platform type (i.e., server vs. desktop), or security goals. That said, it's important to consider Group Policy needs when you're designing (or redesigning) AD. Keep these design goals in mind during your AD design discussions:

  • Try to deploy 80 percent of your GPOs without requiring filtering.
  • Find an OU design that lets you link close to the target for 80 percent of your scenarios.
  • The other 20 percent should require compromises, not AD redesigns.
  • Avoid designs that force you to link and enforce at the domain level. Such designs make downstream changes more difficult. Reserve linking at the domain level for truly global settings, which should be few and far between.
  • Avoid overly flat OU structures (i.e., all users in one OU) if you plan to use per-user policy in any significant way. Such structures require massive reliance on security filtering, which adds tremendous complexity and risk (e.g., large numbers of objects might be mistargeted if the wrong filter is applied).
  • Avoid designs that require loopback for all computers. Loopback should be reserved for scenarios such as kiosk systems, Remote Desktop Services servers, and so on.

Now that we've talked about high-level principles for designing and deploying GPOs, let's dig into some of the technical aspects around how GPOs are processed and how different deployment decisions can affect Group Policy processing performance.

Understanding Group Policy Processing

A big part of the decision process for designing and deploying GPOs is understanding how Group Policy processing occurs under the best circumstances (and what happens when circumstances are not optimal). To that end, let's talk about the different ways that GPOs are processed. Some of this might be review for you, but it's important foundational knowledge for understanding more complex scenarios.

Background vs. foreground processing. As you know, there are two types of Group Policy processing events: foreground and background. For computers, foreground processing happens on startup. For users, processing happens at logon. Background processing, as the name implies, occurs periodically, based on the client's role. Domain controllers (DCs) perform a background refresh every 5 minutes, whereas client OS versions and regular Windows servers perform a refresh every 90 minutes plus a 30-minute, randomized interval. In addition, Windows Vista and later clients perform a background refresh based on network state. Specifically, if a Windows client (e.g., a roaming laptop) is out of contact with a DC when a background refresh is due, that client immediately performs a background refresh as soon as the DC becomes available. This refresh is often referred to as a network location awareness (NLA) refresh.

Synchronous vs. asynchronous processing. Another important aspect of Group Policy processing that has significant performance ramifications is the distinction between synchronous and asynchronous Group Policy processing. To understand synchronous processing, let's look at a typical example of Group Policy processing from bootup to user logon.

When a Windows computer starts, there's a point at which the client connects to the network. At that point, computer-based Group Policy processing kicks off. If this processing is configured to run synchronously, the user doesn’t see the logon dialog box (aka the Graphical Identification and Authentication -- GINA) until the processing is completed. After the user logs on to the system, user-based Group Policy processing begins; the user doesn’t see the desktop until that processing finishes. Thus, synchronous processing elongates the time it takes for a user to boot up the system, log on, and get productive.

But starting with Windows XP, Microsoft set the default for foreground Group Policy processing as asynchronous. This type of processing is also called Fast Logon Optimization and remains the default foreground processing method through Windows 8 . Asynchronous processing basically tells Windows to continue doing what it was doing, even if Group Policy processing is still running. So, when a computer boots up, it doesn't wait for computer-based Group Policy processing to finish before presenting the user with the logon dialog box. Likewise, when the user logs on, there is no waiting on user Group Policy processing before presenting the user with the desktop.

Most folks read this and think, "Why would I ever want to run Group Policy processing synchronously?" The answer, as many of you have likely discovered, is that some Group Policy client-side extensions (i.e., Software Installation, Folder Redirection, Disk Quota, and Group Policy Preferences Drive Mappings) work only when run synchronously. So, some folks essentially disable asynchronous processing to ensure that these policy areas do what they’re supposed to do. These people enable the somewhat-mislabeled Computer Configuration\Policies\Administrative Templates\System\Logon\ Always Wait for the network at computer startup and user logon policy setting to force synchronous foreground processing.

The truth is, if you're willing to wait for a few computer restarts or user logons for these policy areas to take effect, you probably don't need to kill all the benefits of asynchronous processing by enabling this policy setting. The four policy areas that require synchronous foreground processing will signal to Windows to run synchronously the next time foreground system processing occurs, to ensure that they can process their settings. And I should mention: Background processing is, by definition, always asynchronous.

The Role of Change in Group Policy Processing

One big optimization that Microsoft has included in Group Policy from the very beginning is that, regardless of whether an event is processed in the foreground or the background, no processing occurs if nothing has changed within the GPOs that apply to a given computer or user. In such cases, Group Policy processing goes through the motions of reading all the GPOs that apply. But if, when comparing an existing GPO in AD with its record in the client's registry of what was done last time, the Group Policy engine notices that no changes have occurred, then each client-side extension that implements that policy area simply "walks away." Exceptions to this behavior can occur, such as when someone issues a Gpupdate /force command from a client. This command essentially says, "I don't care whether anything has changed -- go ahead and reprocess all policy anyway."

What constitutes a change that the Group Policy client cares about? Here are some types of changes that trigger a full reprocessing of policy:

  • Someone makes a change that increments a GPO's version number. A difference in version numbers between the current, live GPO and the version number that the client last processed is considered a change.
  • The list of GPOs that apply to a computer or user has changed. Causes for such a change include changes to security group filters on a GPO, changes to WMI filters that are linked to a GPO, or computer or user security group membership changes that cause a GPO to fall in or out of scope.

Note that even when changes trigger a full refresh of policy, not all client-side extensions completely refresh their settings. Let's say that you've deployed Microsoft Office via Group Policy Software Installation. Even if changes cause the Software Installation client-side extension to reprocess the GPO that delivered Office, that client-side extension isn't going to uninstall and reinstall Office. The extension simply reads the GPO's settings and makes sure that nothing major has changed (e.g., you've actually removed Office from the GPO).

The point is that if your environment is relatively static, the computer startup and user logon processes should not be dominated by Group Policy processing. Processing should occur in milliseconds in most environments or in a few seconds in the largest environments.

Group Policy Processing Performance

The topic of Group Policy processing performance is always a touchy one. No one wants his or her GPO deployment to land on the CIO's top 10 list of reasons why users are unhappy with desktop performance. As a result, it's important to think about your Group Policy design in the context of having little impact on the user's desktop experience. To that end, let's talk about Group Policy behaviors and design decisions that can minimize this impact. First, understand where time is typically spent during Group Policy processing, which is composed of two distinct phases: core processing and client-side extension processing.

During the core processing phase, the user or computer determines which GPOs apply and which client-side extensions must perform work. This phase is also when the Group Policy client determines whether something has changed and whether it needs to take action.

During the client-side extension processing phase, the hard work is performed. Each client-side extension that's registered on a system and that has work wakes up and process all the GPOs that were identified during the core phase. This second phase is when the actual settings are applied to the client system. In terms of proportion of overall time spent in Group Policy processing, the client-side extension processing phase easily consumes the greatest amount, as Figure 1 shows.

Figure 1: Comparing Core and Client-Side Extension Processing Times

This pattern doesn't change much even when the client is processing many, many GPOs. It's just the nature of the beast. The time necessary to query AD for GPO information is generally much less than the time spent writing keys to the registry, installing software, mapping drives, and so on. Remember the question I brought up at the beginning of this article: "How many GPOs are too many?" To that point, the number of GPOs that you have is less important than what those GPOs are doing. If you have many GPOs that are each doing many things, then your GPO deployment will definitely affect the user's desktop experience. If you have many GPOs and half of them deploy only one registry policy setting, then the impact will be less. There's also the question of whether you want to maintain so many GPOs that are doing so little, but that's a separate consideration -- one that I'd file under managing complexity.

There's also the question of how often your GPOs are changing. A ton of GPOs that rarely or never change aren't going to have much ongoing effect on your users, other than when a change does occur.

Assessing Client-Side Extension Performance

Now let's look at some low-hanging fruit around client-side extension performance. Examine the following client-side extensions, which are commonly examined around Group Policy processing performance:

  • Client-side extensions such as Software Installation -- which could be processing long-running software installations, or Folder Redirection, which copies user profile files around the network, take a long time to process the first time through. I'm not suggesting that you don't use these features. Rather, keep in mind that the first time they run, they'll usually have a heavy impact on users.
  • The Security client-side extension -- particularly using file or registry security against large trees of files or registry keys -- can take a long time to process. This processing can have a significant impact, even during background processing, as the client-side extension churns through the resources that must be repermissioned. I typically avoid doing these kinds of large-scale permission-change tasks in Group Policy. A better method is to deliver the changes by using a one-time automation script or similar method.
  • The Scripts client-side extension -- more specifically, startup or logon scripts -- are highly problematic from a performance perspective. Group Policy lets you have multiple scripts processing during a given startup or logon. That isn't necessarily a good thing. Scripts have a tendency to linger in environments for years. Some run even though they long ago became irrelevant. Some network-intensive tasks access network resources that are no longer available. To top it off, most scripts don't have good logging, so troubleshooting delays caused by Group Policy–based scripts can be difficult. With the advent of Group Policy preferences, I typically recommend that, whenever possible, shops migrate common script tasks such as drive mappings, printer mappings, or simple registry tweaks to Group Policy preferences. It's a much more robust mechanism with a more complete troubleshooting infrastructure than you get with scripts.

Grouping Client-Side Extensions and Impact on Performance

Two distinct decisions that you can make about organizing your GPOs will have an important impact on performance.

The first decision relates to grouping frequently changing policy areas. Earlier, I alluded to possible performance effects that relate to the decision to go with monolithic or functional GPOs. When you create monolithic GPOs that contain multiple policy areas, you might be inadvertently increasing Group Policy processing times. Why? The problem has to do with how the Group Policy engine detects a change to a GPO (which ultimately determines whether work must take place). That detection mechanism uses a simple version-number check on the GPO. So any change to a GPO requires that all client-side extensions that are implemented in that GPO must do work at the next processing cycle. Why? Because the Group Policy client has no way of knowing which policy area was changed in the GPO; it knows only that something changed.

To better illustrate this concept, let's use a concrete example. Suppose that a computer processes three GPOs: GPO A, GPO B, and GPO C. GPO A and GPO B implement registry and security policy settings. GPO C implements registry policy only. You decide to make a change to security policy on GPO A. The next time Group Policy processing runs, it notices that the version number on GPO A has changed, but it doesn't know which policy area was changed. So processing must tell the registry and security client-side extensions that they both must process settings. In addition, even though GPO C has only registry policy implemented, the registry client-side extension must perform work, so it must process all GPOs within the computer object's GPO hierarchy. Processing only GPO A and GPO B would break that processing hierarchy. Figure 2 illustrates the process.

Figure 2: How Grouping of CSEs Affects Performance

Suddenly, a simple change to one policy area in one GPO requires two client-side extensions to perform work across three GPOs. The moral of the story is that if you have frequently changing policy areas, grouping them together or putting them alone is better than mixing them with policy areas that don't change much. In the previous example, this approach would equate to moving the security policy areas out of GPO A and GPO B and putting them into their own GPO (or GPOs). Then, if you made a change to one of those areas, only the security client-side extension would need to work, and only against the GPOs that implemented the settings.

The second decision relates to our discussion about synchronous versus asynchronous processing. I mentioned four policy areas (i.e., Software Installation, Folder Redirection, Disk Quota, and Group Policy Preferences Drive Mappings) that require synchronous foreground processing. Further, if any of these areas are implemented in a GPO and that GPO changes, then when any of these four client-side extensions process that changed GPO, they tell Windows to run the next foreground-processing cycle synchronously, even if the system is configured to run asynchronous foreground processing. And of course, if synchronous processing is configured, it elongates both machine-startup and user-logon times. Again, proper grouping of policy areas in GPOs comes into play. If you have a GPO that implements, say, Group Policy Preferences Drive Mappings and Registry policy, and you make a change to a registry policy setting in that GPO, then when the client processes the GPO, it doesn't know which policy area changed -- only that a change happened. So both the registry and Group Policy Preferences Drive Mapping client-side extensions fire up. The Drive Mapping client-side extension tells Windows to run the next foreground cycle synchronously "just in case," and suddenly an innocent little change to registry policy causes the next reboot or user logon to run slower! Just as in the previous decision around versioning and grouping of client-side extensions, when you're implementing one of these four synchronous policy areas, the best practice is to either put them in GPOs of their own or to combine them with each other, separate from policy areas that don't require synchronous processing.

Group Policy Performance and Loopback

It's worth saying a word about loopback and its potential impact on performance. As you probably know, loopback processing is typically used in kiosk, Remote Desktop Services, or Citrix XenApp environments. This type of processing comes in two modes: merge and replace. Merge mode has potential performance effects, depending on where your GPOs are linked in relation to computers that are enabled for loopback. That's because merge mode first processes user settings for the user object that's logging on to the loopback computer, then processes user settings that apply to the loopback computer object. This presents an interesting possibility: For example, the same GPO containing logon scripts or other settings can actually process twice, if it's linked and filtered in such a way that it applies to both user and computer objects. The point here is that if you need or plan to use merge mode, use the Resultant Set of Policy (RSoP) modeling tools that come with Group Policy Management Console to determine what the effect will be on the user. That impact could literally double the time spent processing policy.

Seen But Not Heard

There are many things to think about when designing a well-performing Group Policy deployment. You'll need to consider everything from your AD design and where you link and filter your GPOs to how you group settings together. At the end of the day, a good Group Policy design should be "seen but not heard." Your users should not know that they're being managed by Group Policy. And you definitely don't want your CIO asking why Group Policy is causing so many problems. Plan, test, and deploy for optimal performance and security, using the guidelines that I've discussed here, and you -- and your policies -- will be in good shape.