diff --git a/server/managers/ApiCacheManager b/server/managers/ApiCacheManager
index 9d80fdb2..882b9b61 100644
--- a/server/managers/ApiCacheManager
+++ b/server/managers/ApiCacheManager
@@ -1,42 +1,47 @@
 const { LRUCache } = require('lru-cache')
 const Logger = require('../Logger')
-const { measure } = require('../utils/timing')
+const Database = require('../Database')
 
 class ApiCacheManager {
-  constructor() {
-    this.options = {
-      max: 1000,
-      maxSize: 10 * 1000 * 1000,
-      sizeCalculation: item => item.length,
-    }
+  constructor(options = { max: 1000, maxSize: 10 * 1000 * 1000, sizeCalculation: item => item.length }) {
+    this.options = options
   }
 
-  init() {
+  init(database = Database) {
     this.cache = new LRUCache(this.options)
+    let hooks = ['afterCreate', 'afterUpdate', 'afterDestroy', 'afterBulkCreate', 'afterBulkUpdate', 'afterBulkDestroy']
+    hooks.forEach(hook => database.sequelize.addHook(hook, (model) => this.clear(model, hook)))
+  }
+
+  clear(model, hook) {
+    Logger.debug(`[ApiCacheManager] ${model.constructor.name}.${hook}: Clearing cache`)
+    this.cache.clear()
   }
 
   get middleware() {
     return (req, res, next) => {
-      measure('ApiCacheManager.middleware', () => {
-        const key = req.originalUrl || req.url
-        Logger.debug(`[ApiCacheManager] Cache key: ${key}`)
-        Logger.debug(`[ApiCacheManager] Cache: ${this.cache} count: ${this.cache.size} size: ${this.cache.calculatedSize}`)
-        const cached = this.cache.get(key)
-        if (cached) {
-          Logger.debug(`[ApiCacheManager] Cache hit: ${key}`)
-          res.send(cached)
-          return
+      const key = { user: req.user.username, url: req.url }
+      const stringifiedKey = JSON.stringify(key)
+      Logger.debug(`[ApiCacheManager] count: ${this.cache.size} size: ${this.cache.calculatedSize}`)
+      Logger.debug(`[ApiCacheManager] Cache key: ${stringifiedKey}`)
+      const cached = this.cache.get(stringifiedKey)
+      if (cached) {
+        Logger.debug(`[ApiCacheManager] Cache hit: ${stringifiedKey}`)
+        res.send(cached)
+        return
+      }
+      res.sendResponse = res.send
+      res.send = (body) => {
+        Logger.debug(`[ApiCacheManager] Cache miss: ${stringifiedKey}`)
+        if (key.url.search(/^\/libraries\/.*?\/personalized/) !== -1) {
+          Logger.debug(`[ApiCacheManager] Caching personalized with 30 minues TTL`)
+          this.cache.set(stringifiedKey, body, { ttl: 30 * 60 * 1000 })
+        } else {
+          this.cache.set(stringifiedKey, body)
         }
-        res.sendResponse = res.send
-        res.send = (body) => {
-          Logger.debug(`[ApiCacheManager] Cache miss: ${key}`)
-          measure('ApiCacheManager.middleware: res.send', () => {
-            this.cache.set(key, body)
-            res.sendResponse(body)
-          })
-        }
-        next()
-      })
+        res.sendResponse(body)
+      }
+      next()
     }
   }
 }
diff --git a/server/routers/ApiRouter.js b/server/routers/ApiRouter.js
index 43c32628..e499b2cf 100644
--- a/server/routers/ApiRouter.js
+++ b/server/routers/ApiRouter.js
@@ -68,20 +68,20 @@ class ApiRouter {
 
     this.router.get('/libraries/:id/items', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getLibraryItems.bind(this))
     this.router.delete('/libraries/:id/issues', LibraryController.middleware.bind(this), LibraryController.removeLibraryItemsWithIssues.bind(this))
-    this.router.get('/libraries/:id/episode-downloads', LibraryController.middleware.bind(this), LibraryController.getEpisodeDownloadQueue.bind(this))
-    this.router.get('/libraries/:id/series', LibraryController.middleware.bind(this), LibraryController.getAllSeriesForLibrary.bind(this))
+    this.router.get('/libraries/:id/episode-downloads', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getEpisodeDownloadQueue.bind(this))
+    this.router.get('/libraries/:id/series', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getAllSeriesForLibrary.bind(this))
     this.router.get('/libraries/:id/series/:seriesId', LibraryController.middleware.bind(this), LibraryController.getSeriesForLibrary.bind(this))
-    this.router.get('/libraries/:id/collections', LibraryController.middleware.bind(this), LibraryController.getCollectionsForLibrary.bind(this))
-    this.router.get('/libraries/:id/playlists', LibraryController.middleware.bind(this), LibraryController.getUserPlaylistsForLibrary.bind(this))
-    this.router.get('/libraries/:id/personalized', LibraryController.middleware.bind(this), LibraryController.getUserPersonalizedShelves.bind(this))
-    this.router.get('/libraries/:id/filterdata', LibraryController.middleware.bind(this), LibraryController.getLibraryFilterData.bind(this))
-    this.router.get('/libraries/:id/search', LibraryController.middleware.bind(this), LibraryController.search.bind(this))
+    this.router.get('/libraries/:id/collections', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getCollectionsForLibrary.bind(this))
+    this.router.get('/libraries/:id/playlists', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getUserPlaylistsForLibrary.bind(this))
+    this.router.get('/libraries/:id/personalized', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getUserPersonalizedShelves.bind(this))
+    this.router.get('/libraries/:id/filterdata', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getLibraryFilterData.bind(this))
+    this.router.get('/libraries/:id/search', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.search.bind(this))
     this.router.get('/libraries/:id/stats', LibraryController.middleware.bind(this), LibraryController.stats.bind(this))
-    this.router.get('/libraries/:id/authors', LibraryController.middleware.bind(this), LibraryController.getAuthors.bind(this))
-    this.router.get('/libraries/:id/narrators', LibraryController.middleware.bind(this), LibraryController.getNarrators.bind(this))
+    this.router.get('/libraries/:id/authors', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getAuthors.bind(this))
+    this.router.get('/libraries/:id/narrators', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.getNarrators.bind(this))
     this.router.patch('/libraries/:id/narrators/:narratorId', LibraryController.middleware.bind(this), LibraryController.updateNarrator.bind(this))
     this.router.delete('/libraries/:id/narrators/:narratorId', LibraryController.middleware.bind(this), LibraryController.removeNarrator.bind(this))
-    this.router.get('/libraries/:id/matchall', LibraryController.middleware.bind(this), LibraryController.matchAll.bind(this))
+    this.router.get('/libraries/:id/matchall', LibraryController.middleware.bind(this), cacheMiddleware, LibraryController.matchAll.bind(this))
     this.router.post('/libraries/:id/scan', LibraryController.middleware.bind(this), LibraryController.scan.bind(this))
     this.router.get('/libraries/:id/recent-episodes', LibraryController.middleware.bind(this), LibraryController.getRecentEpisodes.bind(this))
     this.router.get('/libraries/:id/opml', LibraryController.middleware.bind(this), LibraryController.getOPMLFile.bind(this))