A Microsoft Entra ID dynamic group keeps its membership in sync with a rule written as <object>.<property> <operator> <value>, for example user.department -eq "Sales" or device.deviceOwnership -eq "Company". You combine expressions with -and, -or and -not, use -any and -all for multi-value properties such as proxyAddresses, and Entra ID adds or removes users or devices automatically whenever their attributes change. This guide gives you the syntax rules that trip people up, a set of user and device rules you can paste in, and the steps to validate, monitor and troubleshoot them.
Who this is for and what you will have at the end
This guide is for identity and endpoint administrators who assign licences, Conditional Access policies, apps or Intune profiles to groups and are tired of maintaining membership by hand. It assumes you are comfortable in the Microsoft Entra admin center and have used Microsoft Graph PowerShell before.
At the end you will have:
- A clear picture of the rule grammar: properties, operators, values, nulls, quoting and precedence.
- A library of user rules (department, domain, licence state, extension attributes, direct reports) and device rules (Autopilot, ownership, join type, management).
- A repeatable way to create and convert groups in the portal and in PowerShell.
- A validation and monitoring routine, and fixes for the parser errors you are most likely to see.
- A plan for the
memberOfoperator, whose preview stops updating groups on 3 November 2026.
Prerequisites and limits
Check these before you build anything:
| Item | Detail |
|---|---|
| Licence | Microsoft Entra ID P1 (or Intune for Education) for every unique user who is a member of at least one dynamic group. Devices need no licence. |
| Role | At least Groups Administrator to create, edit, validate or pause dynamic groups |
| Group types | Security groups (users or devices) and Microsoft 365 groups (users only) |
| Tenant limit | 15,000 dynamic membership groups |
| Rule length | The rule body can't exceed 3,072 characters |
| Rule builder | Up to five expressions, user rules only; device rules need the text box |
| Mixing | One rule can't contain both users and devices |
Two design constraints matter early. First, a group that is assignable to Microsoft Entra roles can't use dynamic membership, so admin role groups stay assigned. Second, you can't manually add or remove members of a dynamic group; the rule is the only source of truth.
Microsoft also flags a security consideration: a dynamic group is only as trustworthy as the attributes in its rule. If users can write to an attribute (for example, an on-premises attribute with SELF write permission that syncs to Entra ID), they can add themselves to the group. Audit write permissions on every attribute you use, in Entra ID and at the source, before you use a dynamic group for Conditional Access or access to sensitive data.
How a membership rule is built
A single expression has three parts in a fixed order: property, operator, value.
user.department -eq "Sales"Operators
| Operator | Syntax | Notes |
|---|---|---|
| Equals / Not Equals | -eq / -ne | Use for exact values and null checks |
| Starts With / Not Starts With | -startsWith / -notStartsWith | Efficient for prefixes |
| Ends With / Not Ends With | -endsWith / -notEndsWith | Efficient for suffixes such as domains |
| Contains / Not Contains | -contains / -notContains | Partial string match; slower, text box only |
| Match / Not Match | -match / -notMatch | Regular expressions; slowest |
| In / Not In | -in / -notIn | Compare against a bracketed list |
| Less/greater than | -le / -ge | Used with employeeHireDate |
The hyphen is optional, but keep it for readability. Logical operators are -and, -or and -not, and the collection operators are -any and -all.
Syntax rules that cause most failures
- Property names are case sensitive. Write them exactly as documented, for example
userPrincipalName, notUserPrincipalName. - String comparisons and regular expressions are not case sensitive.
- Wrap string values in double quotation marks. If the value itself contains double quotes, escape each one with a backtick; escape a single quote by doubling it.
- Check for empty values with
nullunquoted, and only with-eqor-ne. Quoting"null"makes it a literal string, and using-notagainst null throws an error. - Precedence runs from comparison operators, then
-not, then-and, then-or, then-anyand-all. Add parentheses whenever you mean something else.
user.country -eq "US" -and (user.department -eq "Marketing" -or user.department -eq "Sales")User rule examples
All members of the organization, excluding guests:
(user.objectId -ne null) -and (user.userType -eq "Member")Drop the second expression and the group also includes B2B guests.
Several departments without a chain of -or operators:
user.department -in ["Finance", "Legal", "Procurement"]Users whose UPN is in one domain, and enabled accounts only:
(user.userPrincipalName -endsWith "@contoso.com") -and (user.accountEnabled -eq true)Users synchronized from on-premises Active Directory:
user.dirSyncEnabled -eq trueAn extension attribute set by HR or synced from Active Directory (extensionAttribute1 to extensionAttribute15 are supported):
user.extensionAttribute15 -eq "Marketing"A custom directory extension uses the format user.extension_<appIdWithoutHyphens>_<attributeName>. In the rule builder, Get custom extension properties lists them when you enter the owning application's ID.
user.extension_c272a57b722d4eb29bfe327874ae79cb_OfficeNumber -eq "123"Any proxy address in a given domain, using the underscore placeholder for each item in a collection:
(user.proxyAddresses -any (_ -endsWith "@fabrikam.com"))Rules based on licence state
assignedPlans exposes servicePlanId, service and capabilityStatus for each service plan. Users with Exchange Online (Plan 2) enabled:
user.assignedPlans -any (assignedPlan.servicePlanId -eq "efb87545-963c-4e0d-99df-69c6916d9eb0" -and assignedPlan.capabilityStatus -eq "Enabled")Users with any enabled Intune service plan (service name SCO), which is a handy scope for Intune user-targeted policies:
user.assignedPlans -any (assignedPlan.service -eq "SCO" -and assignedPlan.capabilityStatus -eq "Enabled")To find the service plan IDs a user actually has, query them with Microsoft Graph PowerShell:
Connect-MgGraph -Scopes 'User.Read.All'
Get-MgUser -UserId adele@contoso.com -Property assignedPlans |
Select-Object -ExpandProperty assignedPlans |
Select-Object service, servicePlanId, capabilityStatus | Format-ListRemember that service plans are not the same thing as licence SKUs; one SKU contains many plans.
Direct reports and hire date
A direct reports group contains a manager's direct reports, plus the manager. It only works when the Manager attribute is populated, only covers one level, and can't be combined with any other expression:
Direct Reports for "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb"employeeHireDate (preview) accepts dates and the system.now keyword:
user.employeeHireDate -ge system.now -plus p1dDevice rule examples
Device rules are written in the text box; the rule builder doesn't support them.
| Goal | Rule |
|---|---|
| All devices | device.objectId -ne null |
| All Windows Autopilot devices | device.devicePhysicalIds -any _ -startsWith "[ZTDId]" |
| Autopilot devices from one order | device.devicePhysicalIds -any _ -eq "[OrderID]:179887111881" |
| Devices enrolled with a named profile | device.enrollmentProfileName -eq "DEP iPhones" |
| Corporate-owned devices | device.deviceOwnership -eq "Company" |
| Microsoft Entra joined devices | device.deviceTrustType -eq "AzureAD" |
| Microsoft Entra hybrid joined devices | device.deviceTrustType -eq "ServerAD" |
| Intune-managed devices | device.deviceManagementAppId -eq "0000000a-0000-0000-c000-000000000000" |
| iPads and iPhones | (device.deviceOSType -eq "iPad") -or (device.deviceOSType -eq "iPhone") |
| Windows 10 builds | device.deviceOSVersion -startsWith "10.0.1" |
Three values differ from what you see elsewhere:
deviceOwnershipmust beCompany, even though Intune shows the same state as Corporate.deviceTrustTypeusesAzureADfor Entra joined,ServerADfor hybrid joined andWorkplacefor Entra registered devices.organizationalUnitis no longer listed and shouldn't be used; Entra ID doesn't recognize it and no devices are added based on it.
To confirm the exact OS version string a device reports, use Get-MgDevice:
Get-MgDevice -Search "displayName:LAPTOP-0142" -ConsistencyLevel eventual |
Select-Object -ExpandProperty OperatingSystemVersionDynamic groups or Intune assignment filters
Microsoft's guidance is to use Intune assignment filters when they meet the targeting need for Intune apps and policies, because filters include or exclude managed devices within an assigned group at evaluation time. Keep dynamic device groups for scenarios outside Intune assignments, or across workloads: Conditional Access, licensing and Autopilot profile assignment are the common ones. A typical pattern is one dynamic group of all Autopilot devices for the deployment profile, and filters for model- or OS-specific app targeting.
Create a dynamic group
In the Microsoft Entra admin center
- Sign in to the Microsoft Entra admin center as at least a Groups Administrator.
- Go to Microsoft Entra ID > Groups > All groups and select New group.
- Enter a name and description, set Membership type to Dynamic User or Dynamic Device, and select Add dynamic query.
- Build up to five expressions in the rule builder, or select Edit and paste the rule into the text box.
- Select Save, then Create.
If the rule is invalid, the portal explains why it couldn't be processed. Read the message; it usually names the property or operator at fault.
With Microsoft Graph PowerShell
The groupTypes value DynamicMembership makes a group dynamic, membershipRule holds the rule and membershipRuleProcessingState set to On starts evaluation:
Connect-MgGraph -Scopes 'Group.ReadWrite.All'
$params = @{
displayName = 'DYN-Devices-Autopilot'
description = 'All Windows Autopilot registered devices'
mailEnabled = $false
mailNickname = 'dyn-devices-autopilot'
securityEnabled = $true
groupTypes = @('DynamicMembership')
membershipRule = 'device.devicePhysicalIds -any _ -startsWith "[ZTDId]"'
membershipRuleProcessingState = 'On'
}
New-MgGroup -BodyParameter $paramsFor a dynamic Microsoft 365 group, groupTypes is @('Unified','DynamicMembership') and the group is mail-enabled.
Convert an existing static group
Converting keeps the group's name and object ID, so existing assignments keep working. Members who match the rule stay, members who don't are removed, and new matches are added. If the group controls access to apps, original members can lose access until processing finishes, so test the rule first. Microsoft's documented approach preserves any other groupTypes values:
$groupId = 'a58913b2-eee4-44f9-beb2-e381c375058f'
$rule = 'user.department -eq "Sales"'
[System.Collections.ArrayList]$groupTypes = (Get-MgGroup -GroupId $groupId).GroupTypes
if ($groupTypes -ne $null -and $groupTypes.Contains('DynamicMembership')) {
throw 'Group is already dynamic.'
}
$groupTypes.Add('DynamicMembership') | Out-Null
Update-MgGroup -GroupId $groupId -GroupTypes $groupTypes.ToArray() `
-MembershipRuleProcessingState 'On' -MembershipRule $ruleValidate and monitor
Validate a rule against real objects
Open the group, select Dynamic membership rules, then the Validate Rules tab. Add up to 20 users or devices; validation starts automatically and shows whether each one would be a member. View details shows the result of every expression in the rule, which is the fastest way to find the clause that excludes someone. A result of Unknown means the rule is invalid or there was a network problem; the details explain which.
Check processing status
The group's Overview page shows Dynamic rule processing status and Last membership change:
| Status | Meaning |
|---|---|
| Not started | Processing hasn't started |
| Evaluating | The change was received and is being evaluated |
| Processing | Updates are being processed |
| Update complete | All applicable updates were made |
| Processing error | The rule couldn't be evaluated |
| Update paused | An administrator paused processing |
The same page has a Pause processing option, available to Groups Administrators but not to group owners without that role. Pausing can be useful before a large rule change on a group that drives licensing.
To audit every dynamic group and its rule in one pass:
Get-MgGroup -Filter "groupTypes/any(s:s eq 'DynamicMembership')" `
-Property "id,displayName,membershipRule,membershipRuleProcessingState" `
-ConsistencyLevel eventual -CountVariable CountVar -Top 999 |
Select-Object DisplayName, MembershipRuleProcessingState, MembershipRuleWrite rules that process quickly
Every attribute change triggers evaluation of every dynamic rule in the tenant, so rule efficiency affects all groups, not just one. Microsoft's recommendations:
- Prefer
-eq, then-startsWithor-endsWith, over-matchand-contains. For a domain,user.userPrincipalName -endsWith "@contoso.com"beatsuser.mail -match ".*@contoso.com$". - Replace long
-orchains on the same property with-in, and long-and ... -nechains with-notIn. - Remove redundant criteria;
user.city -startsWith "Lag"already coversuser.city -eq "Lagos". - Clean up stale devices and inactive users first. Rules evaluate every object, including ones nobody uses any more.
The memberOf preview ends on 3 November 2026
The memberOf operator lets a rule pull in members of other groups, for example user.memberof -any (group.objectId -in ['<groupObjectId>']). It was always a preview with tight limits: 500 such groups per tenant, 50 source groups per rule, direct members only, no combination with other expressions, and no support in the rule builder or the validation tab.
Microsoft is ending the preview. After 3 November 2026, dynamic groups, dynamic administrative units and entitlement management auto-assignment policies that use memberOf stop updating and stay frozen in their last state. That leaves stale Teams and SharePoint access, Conditional Access targeting, licence assignments and access package assignments. Before the deadline:
- List dynamic groups with the PowerShell command above and filter the output for rules containing
memberOf. - Rewrite each rule with supported attribute-based expressions, or convert the group to assigned membership.
- Validate the new membership, and delete groups nobody needs.
Troubleshooting
| Symptom or message | Cause | Fix |
|---|---|---|
Attribute not supported. | The property isn't on the supported list, or its case is wrong | Use a documented property name with exact casing |
Operator isn't supported on attribute. | Wrong operator for the type, such as -contains on a Boolean | Use -eq or -ne for Booleans |
Query compilation error. | Missing -and/-or between expressions, or an invalid regex such as "*@domain.ext" | Join predicates explicitly; use a valid pattern such as "@domain.ext$" |
Dynamic group policies max allowed groups count reached | The tenant is at its dynamic group limit | Delete unused dynamic groups; the limit can't be raised |
| Group stays empty | No objects match, or processing hasn't finished | Check attribute values, then the processing status; allow up to 24 hours |
| Members disappeared after a rule edit | Expected: users who no longer match are removed | Validate rule changes before saving them |
| Changes aren't showing | Evaluation is asynchronous | Wait, or add a trailing space to the rule and save to requeue it |
If processing is delayed across the whole tenant for more than 24 hours, an alert appears above All groups; that is a service-side delay, not a problem with your rule.
Checklist
- Confirm P1 licence coverage for every unique user in dynamic groups.
- Audit who can write each attribute you plan to use.
- Prefer
-eq,-startsWith,-endsWithand-in; avoid-matchand-contains. - Validate against sample users or devices before saving.
- Watch Dynamic rule processing status after every change.
- Use Intune assignment filters for Intune targeting, dynamic groups for Conditional Access, licensing and Autopilot.
- Replace every
memberOfrule before 3 November 2026.
Dynamic groups are a natural way to scope the policies in a Microsoft 365 tenant security baseline and the access model described in the Zero Trust remote access architecture.
References
- Manage rules for dynamic membership groups in Microsoft Entra ID
- Create or edit a dynamic membership group and get its processing status
- Validate rules for dynamic membership groups
- Create simpler and faster rules for dynamic membership groups
- Change static groups to dynamic membership groups
- Configure dynamic membership groups with the memberOf operator (preview)
- Fix problems with dynamic membership groups
- Create group - Microsoft Graph v1.0
- List groups - Microsoft Graph v1.0