diff --git a/lib/private/Preview/Watcher.php b/lib/private/Preview/Watcher.php
new file mode 100644
index 0000000000000000000000000000000000000000..0b87bcda86e13e2e9df9d72296403bf3987ee3c8
--- /dev/null
+++ b/lib/private/Preview/Watcher.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OC\Preview;
+
+use OCP\Files\File;
+use OCP\Files\Node;
+use OCP\Files\Folder;
+use OCP\Files\IAppData;
+use OCP\Files\NotFoundException;
+
+/**
+ * Class Watcher
+ *
+ * @package OC\Preview
+ *
+ * Class that will watch filesystem activity and remove previews as needed.
+ */
+class Watcher {
+	/** @var IAppData */
+	private $appData;
+
+	/** @var int[] */
+	private $toDelete = [];
+
+	/**
+	 * Watcher constructor.
+	 *
+	 * @param IAppData $appData
+	 */
+	public function __construct(IAppData $appData) {
+		$this->appData = $appData;
+	}
+
+	public function postWrite(Node $node) {
+		// We only handle files
+		if ($node instanceof Folder) {
+			return;
+		}
+
+		try {
+			$folder = $this->appData->getFolder($node->getId());
+			$folder->delete();
+		} catch (NotFoundException $e) {
+			//Nothing to do
+		}
+	}
+
+	public function preDelete(Node $node) {
+		// To avoid cycles
+		if ($this->toDelete !== []) {
+			return;
+		}
+
+		if ($node instanceof File) {
+			$this->toDelete[] = $node->getId();
+			return;
+		}
+
+		/** @var Folder $node */
+		$nodes = $node->search('');
+		foreach ($nodes as $node) {
+			if ($node instanceof File) {
+				$this->toDelete[] = $node->getId();
+			}
+		}
+	}
+
+	public function postDelete(Node $node) {
+		foreach ($this->toDelete as $fid) {
+			try {
+				$folder = $this->appData->getFolder($fid);
+				$folder->delete();
+			} catch (NotFoundException $e) {
+				// continue
+			}
+		}
+	}
+}
diff --git a/lib/private/Preview/WatcherConnector.php b/lib/private/Preview/WatcherConnector.php
new file mode 100644
index 0000000000000000000000000000000000000000..4e6e786cec7f9890f30419af947896f5910d9cda
--- /dev/null
+++ b/lib/private/Preview/WatcherConnector.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * @copyright Copyright (c) 2016, Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @author Roeland Jago Douma <roeland@famdouma.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OC\Preview;
+
+use OC\SystemConfig;
+use OCP\Files\Node;
+use OCP\Files\IRootFolder;
+
+class WatcherConnector {
+
+	/** @var IRootFolder */
+	private $root;
+
+	/** @var SystemConfig */
+	private $config;
+
+	/**
+	 * WatcherConnector constructor.
+	 *
+	 * @param IRootFolder $root
+	 * @param SystemConfig $config
+	 */
+	public function __construct(IRootFolder $root,
+								SystemConfig $config) {
+		$this->root = $root;
+		$this->config = $config;
+	}
+
+	/**
+	 * @return Watcher
+	 */
+	private function getWatcher() {
+		return \OC::$server->query(Watcher::class);
+	}
+
+	public function connectWatcher() {
+		// Do not connect if we are not setup yet!
+		if ($this->config->getValue('instanceid', null) !== null) {
+			$this->root->listen('\OC\Files', 'postWrite', function (Node $node) {
+				$this->getWatcher()->postWrite($node);
+			});
+
+			$this->root->listen('\OC\Files', 'preDelete', function (Node $node) {
+				$this->getWatcher()->preDelete($node);
+			});
+
+			$this->root->listen('\OC\Files', 'postDelete', function (Node $node) {
+				$this->getWatcher()->postDelete($node);
+			});
+		}
+	}
+}
diff --git a/lib/private/Server.php b/lib/private/Server.php
index 9f993ade7fec670c83f5ea6c6a707cd7913cc18b..eb6865c4f9b04098884d99c596e67663a5f131ab 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -120,6 +120,12 @@ class Server extends ServerContainer implements IServerContainer {
 			return new PreviewManager($c->getConfig());
 		});
 
+		$this->registerService(\OC\Preview\Watcher::class, function (Server $c) {
+			return new \OC\Preview\Watcher(
+				$c->getAppDataDir('preview')
+			);
+		});
+
 		$this->registerService('EncryptionManager', function (Server $c) {
 			$view = new View();
 			$util = new Encryption\Util(
@@ -192,6 +198,10 @@ class Server extends ServerContainer implements IServerContainer {
 			);
 			$connector = new HookConnector($root, $view);
 			$connector->viewToNode();
+
+			$previewConnector = new \OC\Preview\WatcherConnector($root, $c->getSystemConfig());
+			$previewConnector->connectWatcher();
+
 			return $root;
 		});
 		$this->registerService('LazyRootFolder', function(Server $c) {