extern BlueSkyOptions bluesky_options;
 
+/* Maximum number of threads to use in any particular thread pool, or -1 for no
+ * limit */
+extern int bluesky_max_threads;
+
 /* BlueSky status and error codes.  Various frontends should translate these to
  * the appropriate error code for whatever protocol they implement. */
 typedef enum {
 
 
 BlueSkyOptions bluesky_options;
 
+/* Maximum number of threads to use in any particular thread pool, or -1 for no
+ * limit */
+int bluesky_max_threads = -1;
+
 /* Environment variables that can be used to initialize settings. */
 static struct {
     const char *env;
 
 
     static volatile gsize once = 0;
     if (g_once_init_enter(&once)) {
-        thread_pool = g_thread_pool_new(kvstore_task, NULL, -1, FALSE, NULL);
+        thread_pool = g_thread_pool_new(kvstore_task, NULL,
+                                        bluesky_max_threads, FALSE, NULL);
         g_once_init_leave(&once, 1);
     }
 
 
 void bluesky_store_init()
 {
     store_implementations = g_hash_table_new(g_str_hash, g_str_equal);
-    notifier_thread_pool = g_thread_pool_new(notifier_task, NULL, -1, FALSE,
-                                             NULL);
+    notifier_thread_pool = g_thread_pool_new(notifier_task, NULL,
+                                             bluesky_max_threads, FALSE, NULL);
     bluesky_store_register(&memstore_impl, "mem");
     bluesky_store_register(&filestore_impl, "file");
 }
 
     main_context = g_main_context_new();
     main_loop = g_main_loop_new(main_context, FALSE);
 
-    rpc_thread_pool = g_thread_pool_new(async_rpc_task, NULL, -1, FALSE, NULL);
+    rpc_thread_pool = g_thread_pool_new(async_rpc_task, NULL,
+                                        bluesky_max_threads, FALSE, NULL);
 
     /* Arrange to have the cache writeback code run every five seconds. */
     GSource *source = g_timeout_source_new_seconds(5);