diff --git a/README.md b/README.md
index 5fcfb256a924060bb94a362af4629e1fd4a61a45..8f017c500317da48692baacb3e8723368ff65c0d 100644
--- a/README.md
+++ b/README.md
@@ -75,7 +75,21 @@ This tool requires the following OAuth2 scopes to actually perform changes:
 See the section on preparing a service account for information on how to grant a
 service account those scopes on your domain.
 
-## Preparing a service account
+## Preparing a service account (Admin Roles)
+
+Google have [updated the API](https://gsuiteupdates.googleblog.com/2020/08/use-service-accounts-google-groups-without-domain-wide-delegation.html)
+to allow service accounts direct access to the API without needing domain-wide delegation.
+
+1. Create a service account in the Google Console for this script.
+2. Generate and download JSON credentials for the service account.
+3. In the GSuite admin panel, go to "Account" > "Admin Roles" and create a new
+custom role with the following Admin **API** privileges (not Console privileges):
+   * Users - Create, Read, Update and Update Custom Attributes
+   * Groups - All privileges
+4. Add the service account to the role using the "Assign service accounts" option
+when viewing the custom role's admins
+
+## Preparing a service account (Domain-wide Delegation)
 
 This tool assumes it will be acting as a service account user. It will use this
 service account user to then act on behalf of an admin user in GSuite. To
@@ -88,8 +102,8 @@ prepare such a service account user:
    Delegation". Click "Save" to apply the changes.
 4. Hover over the "?" symbol next to the generated client id and click "view
    client". Copy the Client ID from the popup panel.
-5. In the GSuite admin panel, go to "Security Settings" > "Advanced Settings" >
-   "Manage API client access".
+5. In the GSuite admin panel, go to "Security Settings" > "API Controls" >
+   "Manage Domain-Wide Delegation", and click "Add new".
 6. Paste in the service account Client ID as "Client Name" and add a
    comma-separated list of scopes. See the section on required API scopes.
 
diff --git a/configuration-example.yaml b/configuration-example.yaml
index 04819734383cf1118e27fae9d5f638b634980046..fafa8a58db61be09d6a30a37a2065f372f5c0150 100644
--- a/configuration-example.yaml
+++ b/configuration-example.yaml
@@ -190,10 +190,14 @@ google_domain:
   # Name of the domain.
   name: 'example.com'
 
-  # Username within the GSuite for the user which has administration rights.
+  # If using a service account with Domain-Wide Delegation, set to the username
+  # within the GSuite for the user which has administration rights.
   # Should be an e-mail style name. E.g. "super-admin@example.com". The service
   # account credentials specified in the google_api.auth section are used to
   # perform admin actions as this user.
+  # If not using Domain-Wide Delegation (i.e. the service account executing this
+  # script has been made a member of an Admin Role), use null or comment out.
+  # Default: null
   admin_user: 'super-admin@example.com'
 
   # Secondary domain or domain alias for groups. If null, the value of "name"
diff --git a/gsuitesync/gapidomain.py b/gsuitesync/gapidomain.py
index 21d0923896d7e3456f76b8d44b1359828ce0ca22..a4dc18c3d12bf712f4ed9c7cc252104eb0aa51eb 100644
--- a/gsuitesync/gapidomain.py
+++ b/gsuitesync/gapidomain.py
@@ -17,10 +17,14 @@ class Configuration(ConfigurationDataclassMixin):
     # Name of the domain. (E.g. "example.com".)
     name: str
 
-    # Username within the GSuite for the user which has administration rights. Should be an e-mail
-    # style name. E.g. "super-admin@example.com". The service account credentials specified in the
-    # google_api.auth section are used to perform admin actions as this user.
-    admin_user: str
+    # If using a service account with Domain-Wide Delegation, set to the username
+    # within the GSuite for the user which has administration rights.
+    # Should be an e-mail style name. E.g. "super-admin@example.com". The service
+    # account credentials specified in the google_api.auth section are used to
+    # perform admin actions as this user.
+    # If not using Domain-Wide Delegation (i.e. using an Admin Role with the
+    # service account as a member), use null.
+    admin_user: str = None
 
     # Secondary domain or domain alias for groups. If None, the value of "name" is used.
     # Default: None
diff --git a/gsuitesync/sync.py b/gsuitesync/sync.py
index a7c5f61474f4d86ff429b507560a2ef2b53a953e..a8a6c4c3f4cd4f36440f3566db3fa72f391636ee 100644
--- a/gsuitesync/sync.py
+++ b/gsuitesync/sync.py
@@ -107,8 +107,10 @@ def sync(configuration, *, read_only=True):
     creds = (
         gapi_auth_config.load_credentials(read_only=read_only)
         .with_scopes(READ_ONLY_SCOPES + ([] if read_only else WRITE_SCOPES))
-        .with_subject(gapi_domain_config.admin_user)
     )
+    # Use admin_user if using service account with Domain-Wide Delegation
+    if gapi_domain_config.admin_user:
+        creds = creds.with_subject(gapi_domain_config.admin_user)
 
     # Secondary domain for Google groups that come from Lookup groups
     groups_domain = (
@@ -173,6 +175,10 @@ def sync(configuration, *, read_only=True):
     eligible_uids = ldap_config.get_eligible_uids()
     LOG.info('Total LDAP user entries: %s', len(eligible_uids))
 
+    # Sanity check: there are some eligible users (else LDAP lookup failure?)
+    if len(eligible_uids) == 0:
+        raise RuntimeError('Sanity check failed: no users in eligible set')
+
     # Get a set containing all groupIDs. These are all the groups that are eligible to be in our
     # GSuite instance. If a group is in GSuite and is *not* present in this list then it is
     # deleted.
diff --git a/setup.py b/setup.py
index 5f6dbbc3df86964603fff3abe4c75483da3db027..88662b8632aa761f9a84e6146be8d8bfbbf7d655 100644
--- a/setup.py
+++ b/setup.py
@@ -17,7 +17,7 @@ def load_requirements():
 
 setup(
     name='gsuitesync',
-    version='0.9.1',
+    version='0.9.2',
     packages=find_packages(),
     install_requires=load_requirements(),
     entry_points={