diff --git a/service-worker.js b/service-worker.js
index 2a083d145aebc277399381101394b63405c4febc..1378414810dbe764ad5d72c1690409e37f3c2003 100644
--- a/service-worker.js
+++ b/service-worker.js
@@ -59,6 +59,31 @@ let decrementActiveFetches = (clientId) => {
     }
 }
 
+/*
+ * returns a Promise that either resolves or rejects after a set timeout
+ * optionally with a specific error message
+ * 
+ * time             - the timeout (in ms)
+ * timeout_resolves - whether the Promise should resolve() or reject() when hitting the timeout (default: false (reject))
+ * error_message    - optional error message to use when rejecting (default: false (no error message))
+ */
+function promiseTimeout(time, timeout_resolves=false, error_message=false) {
+    return new Promise((resolve, reject)=>{
+        setTimeout(()=>{
+            if (timeout_resolves) {
+                resolve(time);
+            } else {
+                if (error_message) {
+                    reject(new Error(error_message))
+                } else {
+                    reject(time)
+                }
+            }
+        },time);
+    });
+};
+
+
 /* ========================================================================= *\
 |* === SamizdatResourceInfo                                              === *|
 \* ========================================================================= */
@@ -219,12 +244,15 @@ let samizdatFetch = (plugin, url, reqInfo) => {
     console.log("(COMMIT_UNKNOWN) Samizdat handling URL:", url,
                 '\n+-- current method : ' + plugin.name)
     // run the plugin
-    return plugin.fetch(url)
+    return Promise.race([
+        plugin.fetch(url),
+        promiseTimeout(10000, false, `Samizdat request using ${plugin.name} timed out.`)
+    ])
 }
 
 
 /**
- * callign a samizdat plugin function
+ * calling a samizdat plugin function
  * 
  * call - method name to call
  * args - arguments that will be passed to it