diff --git a/common/src/main/java/com/google/udmi/util/SiteModel.java b/common/src/main/java/com/google/udmi/util/SiteModel.java
index 0acc72dcb9..d8c8f23dbb 100644
--- a/common/src/main/java/com/google/udmi/util/SiteModel.java
+++ b/common/src/main/java/com/google/udmi/util/SiteModel.java
@@ -272,7 +272,7 @@ public EndpointConfiguration makeEndpointConfig(String iotProject, String device
     return makeEndpointConfig(iotProject, exeConfig, deviceId);
   }
 
-  private Set<String> getDeviceIds() {
+  public Set<String> getDeviceIds() {
     checkState(sitePath != null, "sitePath not defined");
     File devicesFile = new File(new File(sitePath), "devices");
     File[] files = Objects.requireNonNull(devicesFile.listFiles(),
diff --git a/udmis/.idea/runConfigurations/ClearBladeIotAccessProvider.xml b/udmis/.idea/runConfigurations/ClearBladeIotAccessProvider.xml
new file mode 100644
index 0000000000..7a89db79f3
--- /dev/null
+++ b/udmis/.idea/runConfigurations/ClearBladeIotAccessProvider.xml
@@ -0,0 +1,19 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="ClearBladeIotAccessProvider" type="Application" factoryName="Application" nameIsGenerated="true">
+    <envs>
+      <env name="CLEARBLADE_CONFIGURATION" value="$USER_HOME$/creds/bos-platform-dev-credentials.json" />
+    </envs>
+    <option name="MAIN_CLASS_NAME" value="com.google.bos.udmi.service.access.ClearBladeIotAccessProvider" />
+    <module name="udmis" />
+    <option name="PROGRAM_PARAMETERS" value="TW-NTC-TPKD" />
+    <extension name="coverage">
+      <pattern>
+        <option name="PATTERN" value="com.google.bos.udmi.service.access.*" />
+        <option name="ENABLED" value="true" />
+      </pattern>
+    </extension>
+    <method v="2">
+      <option name="Make" enabled="true" />
+    </method>
+  </configuration>
+</component>
\ No newline at end of file
diff --git a/udmis/src/main/java/com/google/bos/udmi/service/access/ClearBladeIotAccessProvider.java b/udmis/src/main/java/com/google/bos/udmi/service/access/ClearBladeIotAccessProvider.java
index b8a14efa15..ddcc257d3c 100644
--- a/udmis/src/main/java/com/google/bos/udmi/service/access/ClearBladeIotAccessProvider.java
+++ b/udmis/src/main/java/com/google/bos/udmi/service/access/ClearBladeIotAccessProvider.java
@@ -67,7 +67,9 @@
 import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableBiMap;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.udmi.util.JsonUtil;
 import java.util.AbstractMap.SimpleEntry;
 import java.util.Base64;
 import java.util.Date;
@@ -95,7 +97,8 @@
 public class ClearBladeIotAccessProvider extends IotAccessBase {
 
   public static final String REGISTRIES_FIELD_MASK = "id,name";
-  private static final Set<String> CLOUD_REGIONS = ImmutableSet.of("us-central1");
+  public static final String DEFAULT_REGION = "us-central1";
+  private static final Set<String> CLOUD_REGIONS = ImmutableSet.of(DEFAULT_REGION);
   private static final String EMPTY_JSON = "{}";
   private static final BiMap<Key_format, PublicKeyFormat> AUTH_TYPE_MAP = ImmutableBiMap.of(
       Key_format.RS_256, PublicKeyFormat.RSA_PEM,
@@ -117,9 +120,31 @@ public class ClearBladeIotAccessProvider extends IotAccessBase {
   private static final String UDMI_STATE_TOPIC = "udmi_state"; // TODO: Make this not hardcoded.
   private static final String TOPIC_NAME_FORMAT = "projects/%s/topics/%s";
   private static final CharSequence BOUND_TO_GATEWAY_MARKER = " it's associated ";
+  public static final String CONFIG_ENV = "CLEARBLADE_CONFIGURATION";
   private final String projectId;
   private final DeviceManagerInterface deviceManager;
 
+  /**
+   * Core test function for listing the devices in a registry.
+   */
+  public static void main(String[] args) {
+    requireNonNull(System.getenv(CONFIG_ENV), CONFIG_ENV + " not defined");
+    IotAccess iotAccess = new IotAccess();
+    if (args.length != 1) {
+      System.err.println("Usage: registry_id");
+      return;
+    }
+    final String registryId = args[0];
+    Map<String, Object> stringObjectMap = JsonUtil.loadMap(System.getenv(CONFIG_ENV));
+    iotAccess.project_id = (String) requireNonNull(stringObjectMap.get("project"));
+    System.err.println("Extracted project from ClearBlade config file: " + iotAccess.project_id);
+    ClearBladeIotAccessProvider clearBladeIotAccessProvider =
+        new ClearBladeIotAccessProvider(iotAccess);
+    clearBladeIotAccessProvider.populateRegistryRegions();
+    CloudModel cloudModel = clearBladeIotAccessProvider.listDevices(registryId);
+    System.err.printf("Found %d results%n", cloudModel.device_ids.size());
+  }
+
   /**
    * Create a new instance for interfacing with GCP IoT Core.
    */
diff --git a/validator/src/main/java/com/google/daq/mqtt/util/IotReflectorClient.java b/validator/src/main/java/com/google/daq/mqtt/util/IotReflectorClient.java
index 5e4f651711..f996105f37 100644
--- a/validator/src/main/java/com/google/daq/mqtt/util/IotReflectorClient.java
+++ b/validator/src/main/java/com/google/daq/mqtt/util/IotReflectorClient.java
@@ -51,10 +51,12 @@ public class IotReflectorClient implements IotProvider {
   // Requires functions that support cloud device manager support.
   private static final String CONFIG_TOPIC_FORMAT = "%s/config";
   private static final File ERROR_DIR = new File("out");
+  public static final double SLOW_QUERY_THRESHOLD = 10000;
   private final com.google.bos.iot.core.proxy.IotReflectorClient messageClient;
   private final Map<String, CompletableFuture<Map<String, Object>>> futures =
       new ConcurrentHashMap<>();
   private final ExecutorService executor = Executors.newSingleThreadExecutor();
+  private final boolean isSlow;
 
   /**
    * Create a new client.
@@ -67,6 +69,11 @@ public IotReflectorClient(ExecutionConfiguration executionConfiguration) {
     messageClient = new com.google.bos.iot.core.proxy.IotReflectorClient(executionConfiguration,
         Validator.TOOLS_FUNCTIONS_VERSION);
     executor.execute(this::processReplies);
+    isSlow = siteModel.getDeviceIds().size() > SLOW_QUERY_THRESHOLD;
+    if (isSlow) {
+      // TODO: Replace this with a dynamic mechanism that gets incremental progress from UDMIS.
+      System.err.println("Using very long list devices timeout because of large number of devices");
+    }
   }
 
   @Override
@@ -156,8 +163,8 @@ public Map<String, CloudModel> fetchCloudModels(String forGatewayId) {
   @Nullable
   private CloudModel fetchCloudModel(String deviceId) {
     try {
-      Map<String, Object> message = transaction(deviceId, CLOUD_QUERY_TOPIC, EMPTY_MESSAGE,
-          QuerySpeed.ETERNITY);
+      QuerySpeed speed = isSlow ? QuerySpeed.ETERNITY : QuerySpeed.SLOW;
+      Map<String, Object> message = transaction(deviceId, CLOUD_QUERY_TOPIC, EMPTY_MESSAGE, speed);
       return convertTo(CloudModel.class, message);
     } catch (Exception e) {
       if (e.getMessage().contains("NOT_FOUND")) {
diff --git a/validator/src/main/java/com/google/daq/mqtt/util/MessagePublisher.java b/validator/src/main/java/com/google/daq/mqtt/util/MessagePublisher.java
index d42bbeaa2b..d62b642a45 100644
--- a/validator/src/main/java/com/google/daq/mqtt/util/MessagePublisher.java
+++ b/validator/src/main/java/com/google/daq/mqtt/util/MessagePublisher.java
@@ -78,7 +78,8 @@ enum QuerySpeed {
     QUICK(1),
     SHORT(15),
     LONG(30),
-    ETERNITY(90);
+    SLOW(90),
+    ETERNITY(600);
 
     private final int seconds;