diff --git a/package-lock.json b/package-lock.json
index 6796e5ac07630fa91a9c03e636cb4a8b617aa03e..faa11a84c55bcfbed36e95737ea505d9261087c1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -484,9 +484,9 @@
       }
     },
     "@types/babel__traverse": {
-      "version": "7.0.7",
-      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.7.tgz",
-      "integrity": "sha512-CeBpmX1J8kWLcDEnI3Cl2Eo6RfbGvzUctA+CjZUhOKDFbLfcr7fc4usEqLNWetrlJd7RhAkyYe2czXop4fICpw==",
+      "version": "7.0.8",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz",
+      "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==",
       "dev": true,
       "requires": {
         "@babel/types": "^7.3.0"
@@ -518,9 +518,9 @@
       }
     },
     "@types/node": {
-      "version": "12.12.7",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz",
-      "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w=="
+      "version": "12.12.11",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.11.tgz",
+      "integrity": "sha512-O+x6uIpa6oMNTkPuHDa9MhMMehlxLAd5QcOvKRjAFsBVpeFWTOPnXbDvILvFgFFZfQ1xh1EZi1FbXxUix+zpsQ=="
     },
     "@types/stack-utils": {
       "version": "1.0.1",
@@ -817,12 +817,12 @@
       "dev": true
     },
     "ansi-escapes": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz",
-      "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==",
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
+      "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
       "dev": true,
       "requires": {
-        "type-fest": "^0.5.2"
+        "type-fest": "^0.8.1"
       }
     },
     "ansi-regex": {
@@ -1911,14 +1911,14 @@
       "dev": true
     },
     "d3-path": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.8.tgz",
-      "integrity": "sha512-J6EfUNwcMQ+aM5YPOB8ZbgAZu6wc82f/0WFxrxwV6Ll8wBwLaHLKCqQ5Imub02JriCVVdPjgI+6P3a4EWJCxAg=="
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
+      "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
     },
     "d3-shape": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.5.tgz",
-      "integrity": "sha512-VKazVR3phgD+MUCldapHD7P9kcrvPcexeX/PkMJmkUov4JM8IxsSg1DvbYoYich9AtdTsa5nNk2++ImPiDiSxg==",
+      "version": "1.3.7",
+      "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
+      "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
       "requires": {
         "d3-path": "1"
       }
@@ -2150,9 +2150,9 @@
       "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
     },
     "ejs": {
-      "version": "2.7.2",
-      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.2.tgz",
-      "integrity": "sha512-rHGwtpl67oih3xAHbZlpw5rQAt+YV1mSCu2fUZ9XNrfaGEhom7E+AUiMci+ByP4aSfuAWx7hE0BPuJLMrpXwOw==",
+      "version": "2.7.4",
+      "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
+      "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
       "dev": true
     },
     "elliptic": {
@@ -2447,9 +2447,9 @@
       }
     },
     "eslint-config-prettier": {
-      "version": "6.5.0",
-      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz",
-      "integrity": "sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ==",
+      "version": "6.7.0",
+      "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz",
+      "integrity": "sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ==",
       "dev": true,
       "requires": {
         "get-stdin": "^6.0.0"
@@ -3703,9 +3703,9 @@
       }
     },
     "handlebars": {
-      "version": "4.5.2",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.2.tgz",
-      "integrity": "sha512-29Zxv/cynYB7mkT1rVWQnV7mGX6v7H/miQ6dbEpYTKq5eJBN7PsRB+ViYJlcT6JINTSu4dVB9kOqEun78h6Exg==",
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+      "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
       "dev": true,
       "requires": {
         "neo-async": "^2.6.0",
@@ -3767,9 +3767,9 @@
       "dev": true
     },
     "has-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
-      "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
+      "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
       "dev": true
     },
     "has-value": {
@@ -4226,12 +4226,12 @@
       "dev": true
     },
     "is-symbol": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
-      "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
+      "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
       "dev": true,
       "requires": {
-        "has-symbols": "^1.0.0"
+        "has-symbols": "^1.0.1"
       }
     },
     "is-typedarray": {
@@ -6349,9 +6349,9 @@
       "dev": true
     },
     "resolve": {
-      "version": "1.12.0",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
-      "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
+      "version": "1.12.2",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz",
+      "integrity": "sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw==",
       "dev": true,
       "requires": {
         "path-parse": "^1.0.6"
@@ -7532,9 +7532,9 @@
       }
     },
     "type-fest": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz",
-      "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==",
+      "version": "0.8.1",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
       "dev": true
     },
     "type-is": {
diff --git a/public/index.html b/public/index.html
index ca2ae6044aece77c536d264245695f3d3464af17..dab54f181c4cc70663bc9a45d5c76b581bbc0e9a 100644
--- a/public/index.html
+++ b/public/index.html
@@ -57,7 +57,9 @@
           size="25"
           color="gray"
         />
-        <button id="room-connect">Connect <i class="fa fa-link"></i></button>
+        <button id="room-connect">
+          Connect <i class="fa fa-link" style="padding: 0 1.5px"></i>
+        </button>
       </div>
       <div id="tools-panel">
         <button id="pen-tool" class="selected">
@@ -197,13 +199,21 @@
             </div>
           </div>
         </div>
-        <button id="eraser-tool"><i class="fa fa-eraser"></i></button>
+        <button id="eraser-tool">
+          <i class="fa fa-eraser" style="padding: 0 1px"></i>
+        </button>
         <div id="status-info">
-          <div id="user-avatar"></div>
+          <button id="fast-undo-tool" class="disabled">
+            <i class="fa fa-fast-backward" style="padding: 0 2.5px"></i>
+          </button>
+          <button id="undo-tool" class="disabled">
+            <i class="fa fa-backward" style="padding: 0 4px 0 1px"></i>
+          </button>
           <div id="connected-room-info">
-            Room <i class="fa fa-globe">: </i> &nbsp;
+            Room:&nbsp;
             <span id="connected-room-id"></span>
           </div>
+          <div id="user-avatar"></div>
         </div>
       </div>
     </div>
diff --git a/public/styles.css b/public/styles.css
index d1f4a1381ed965be737d4eb3082e5c50a941ad2f..578139c8e20b4454ff96fe53c1a2d9e883eced18 100644
--- a/public/styles.css
+++ b/public/styles.css
@@ -33,15 +33,14 @@ body {
   align-items: center;
   background-color: #4f4f4fb7;
   border-radius: 4px;
-  margin-left: 8px;
   justify-content: center;
-  height: 44px;
+  padding: 0.75em;
 }
 
-#connected-room-info:hover {
+/*#connected-room-info:hover {
   background-color: #4f4f4f !important;
   transition-duration: 0.4s;
-}
+}*/
 
 button.selected {
   background-color: gray !important;
@@ -269,6 +268,11 @@ button.selected {
   border-radius: 4px;
 }
 
+#room-connect:hover {
+  background-color: #4f4f4f !important;
+  transition-duration: 0.4s;
+}
+
 #pen-tool {
   background-color: #2f2f2f;
   color: white;
@@ -293,6 +297,7 @@ button.selected {
   border: none;
   cursor: pointer;
   border-radius: 50%;
+  margin-right: 8px;
 }
 
 #eraser-tool:hover {
@@ -300,6 +305,46 @@ button.selected {
   transition-duration: 0.4s;
 }
 
+#undo-tool {
+  background-color: #2f2f2f;
+  color: white;
+  padding: 10px;
+  font-size: 16px;
+  border: none;
+  cursor: pointer;
+  border-radius: 50%;
+  margin-right: 8px;
+}
+
+#undo-tool:hover {
+  background-color: #4f4f4f !important;
+  transition-duration: 0.4s;
+}
+
+#undo-tool.disabled {
+  display: none;
+}
+
+#fast-undo-tool {
+  background-color: #2f2f2f;
+  color: white;
+  padding: 10px;
+  font-size: 16px;
+  border: none;
+  cursor: pointer;
+  border-radius: 50%;
+  margin-right: 8px;
+}
+
+#fast-undo-tool:hover {
+  background-color: #4f4f4f !important;
+  transition-duration: 0.4s;
+}
+
+#fast-undo-tool.disabled {
+  display: none;
+}
+
 .properties {
   display: none;
   position: fixed;
@@ -547,12 +592,14 @@ button.selected {
   align-items: center;
   background-color: #4f4f4fb7;
   border-radius: 4px;
+  margin-left: 0.75em;
+  padding: 0 0.75em 0 0;
 }
 
-#user-avatar:hover {
+/*#user-avatar:hover {
   background-color: #4f4f4f !important;
   transition-duration: 0.4s;
-}
+}*/
 
 #status-info {
   display: flex;
diff --git a/src/app.js b/src/app.js
index 62626b62832d8be6b263f7489d3858eeaf8fea11..10ab8c2cac911c8c1075876b18683de8b32b6081 100644
--- a/src/app.js
+++ b/src/app.js
@@ -158,6 +158,16 @@ const onRoomConnect = (room_) => {
       canvas.renderPath(id, points, room.erasureIntervals[id] || [])
     },
   )
+
+  room.addEventListener("undoEnabled", () => {
+    HTML.fastUndoButton.classList.remove("disabled")
+    HTML.undoButton.classList.remove("disabled")
+  })
+
+  room.addEventListener("undoDisabled", () => {
+    HTML.fastUndoButton.classList.add("disabled")
+    HTML.undoButton.classList.add("disabled")
+  })
 }
 
 const tryRoomConnect = async (roomID) => {
@@ -190,12 +200,20 @@ const onRoomJoinEnter = () => {
 
   canvas.clear()
   HTML.connectedPeers.innerHTML = "No peers are connected"
+  HTML.fastUndoButton.classList.add("disabled")
+  HTML.undoButton.classList.add("disabled")
 
   tryRoomConnect(selectedRoomID)
 }
 
 HTML.roomConnectButton.addEventListener("click", onRoomJoinEnter)
 
+HTML.fastUndoButton.addEventListener(
+  "click",
+  () => room != null && room.fastUndo(),
+)
+HTML.undoButton.addEventListener("click", () => room != null && room.undo())
+
 HTML.roomIDElem.addEventListener("keydown", (event) => {
   if (event.key == "Enter") {
     event.target.blur()
diff --git a/src/elements.js b/src/elements.js
index b1902a21ff6bd350fede2d44e7300c243ab7efa3..d2dd34fb019b214355e71fcbbc0586963bccb9d2 100644
--- a/src/elements.js
+++ b/src/elements.js
@@ -13,6 +13,9 @@ export const canvas = document.getElementById("canvas")
 export const penButton = document.getElementById("pen-tool")
 export const eraserButton = document.getElementById("eraser-tool")
 
+export const fastUndoButton = document.getElementById("fast-undo-tool")
+export const undoButton = document.getElementById("undo-tool")
+
 export const roomIDElem = document.getElementById("room-id")
 export const roomConnectButton = document.getElementById("room-connect")
 export const connectedRoomID = document.getElementById("connected-room-id")
diff --git a/src/room.js b/src/room.js
index a158b5a902f43fa963f10023c76a2d63bbdee235..c0325bb3e821168b29c82201da34d0443a99d3db 100644
--- a/src/room.js
+++ b/src/room.js
@@ -24,6 +24,7 @@ class Room extends EventTarget {
     this._y = null
     this.ownID = null
     this.erasureIntervals = {}
+    this.undoStack = []
   }
 
   disconnect() {
@@ -36,11 +37,25 @@ class Room extends EventTarget {
     this.shared.strokePoints.set(id, Y.Array).push([[x, y, w, colour]])
     this.shared.eraseIntervals.set(id, Y.Union)
 
+    this.undoStack.push([id, 0, 0])
+
+    this.dispatchEvent(new CustomEvent("undoEnabled"))
+
     return id
   }
 
   extendPath(id, [x, y, w, colour]) {
-    this.shared.strokePoints.get(id).push([[x, y, w, colour]])
+    const path = this.shared.strokePoints.get(id)
+
+    path.push([[x, y, w, colour]])
+
+    if (path.length == 2) {
+      this.undoStack[this.undoStack.length - 1] = [id, 0, 1]
+    } else {
+      this.undoStack.push([id, path.length - 2, path.length - 1])
+    }
+
+    this.dispatchEvent(new CustomEvent("undoEnabled"))
   }
 
   extendErasureIntervals(pathID, pointID, newIntervals) {
@@ -49,6 +64,44 @@ class Room extends EventTarget {
       .merge(flattenErasureIntervals({ [pointID]: newIntervals }))
   }
 
+  undo() {
+    const operation = this.undoStack.pop()
+
+    if (!operation) return
+
+    const [id, ...interval] = operation
+
+    this.shared.eraseIntervals.get(id).merge([interval])
+
+    if (this.undoStack.length <= 0) {
+      this.dispatchEvent(new CustomEvent("undoDisabled"))
+    }
+  }
+
+  fastUndo() {
+    let from = this.undoStack.length - 1
+
+    if (from < 0) return
+
+    // eslint-disable-next-line no-unused-vars
+    const [id, _, end] = this.undoStack[from]
+
+    for (; from >= 0; from--) {
+      if (this.undoStack[from][0] != id) {
+        from++
+        break
+      }
+    }
+
+    this.undoStack = this.undoStack.slice(0, Math.max(0, from))
+
+    this.shared.eraseIntervals.get(id).merge([[0, end]])
+
+    if (this.undoStack.length <= 0) {
+      this.dispatchEvent(new CustomEvent("undoDisabled"))
+    }
+  }
+
   getPaths() {
     const paths = new Map()