diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index 6d5079309131d7e5cd22acd9cc5be28073d88770..f74c19bf7b2d2e39ed67b1e699ba05e552ab9689 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -4,7 +4,7 @@ Eventually this will document the architecture of Samizdat.
 
 ## Plugins
 
-There are two kinds of plugins:
+There are three kinds of plugins:
 
 - **Transport plugins**  
   Plugins that *retrieve* website content, e.g. by using regular HTTPS [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), or by going through [IPFS](https://js.ipfs.io/). They *should* also offer a way to *publish* content by website admins (if relevant credentials or encryption keys are provided, depending on the method).  
@@ -12,13 +12,17 @@ Methods these plugins implement:
   - `fetch` - fetch content from an external source (e.g., from IPFS)
   - `publish` - publish the content to the external source (e.g., to IPFS)
 
-* **Stashing plugins**  
+- **Stashing plugins**  
   Plugins that *stash* content locally (e.g., in the [browser cache](https://developer.mozilla.org/en-US/docs/Web/API/Cache)) for displaying when no *transport plugin* works, or before content is received via one of them.  
 Methods these plugins implement:
   - `fetch` - fetch the locally stored content (e.g., from cache)
   - `stash` - stash the content locally (e.g., in cache)
   - `unstash` - clear the content from the local store (e.g., clear the cache)
 
+- **Composing plugins**  
+  Plugins that *compose* other plugins, for example by running them simultaneously to retrieve content from whichever succeeds first.  
+Methods these plugins implement depend on which plugins they compose. Additionally, plugins being composed the `uses` key, providing the configuration for them the same way configuration is provided for plugins in the `plugins` key of `SamizdatConfig`.
+
 Any plugin needs to add itself to the SamizdatPlugins global variable, using a data structure as follows:
 
 ```javascript
@@ -27,7 +31,16 @@ self.SamizdatPlugins.push({
     description: 'Plugin description. Just a few words, ideally.',
     version: 'any relevant plugin version information',
     fetch: functionImplementingFetch,
-    publish|stash|unstash: functionsImplementingRelevantFunctionality
+    publish|stash|unstash: functionsImplementingRelevantFunctionality,
+    uses: {
+        composed-plugin-1: {
+            configKey1: "whatever-data-here"
+        },
+        composed-plugin-2: {
+            configKey2: "whatever-data-here"
+        },
+        {...}
+    }
 })
 ```
 
@@ -45,6 +58,22 @@ Transport plugins *must* add `X-Samizdat-Method` and `X-Samizdat-ETag` headers t
 
 Stashing plugins *must* stash the request along with the `X-Samizdat-Method` and `X-Samizdat-ETag` headers.
 
+### Composing plugins
+
+Composing plugins work by composing other plugins, for example to run them simultaneously and retrieve content from the first one that succeeds. A composing plugin needs to set the `uses` key in it's `SamizdatPlugins`. The key should contain mappings from plugin names to configuration:
+
+```javascript
+uses: {
+    composed-plugin-1: {
+        configKey1: "whatever-data-here"
+    },
+    composed-plugin-2: {
+        configKey2: "whatever-data-here"
+    },
+    {...}
+}
+```
+
 ## Fetching a resource via Samizdat
 
 Whenever a resource is being fetched on a Samizdat-enabled site, the `service-worker.js` script dispatches plugins in the set order. Currently this order is hard-coded in `service-worker.js`, and is: