diff --git a/libs/muExpress.js b/libs/muExpress.js
index 80c5acbb8..9a573ec73 100644
--- a/libs/muExpress.js
+++ b/libs/muExpress.js
@@ -32,6 +32,7 @@ function renderFile(aRes, aPath, aOptions) {
     aOptions.DNT = aRes.oujsOptions.DNT;
     aOptions.hideReminderGDPR = aRes.oujsOptions.hideReminderGDPR;
     aOptions.showReminderListLimit = aRes.oujsOptions.showReminderListLimit;
+    aOptions.showReminderInstallLimit = aRes.oujsOptions.showReminderInstallLimit;
 
     // NOTE: Keep in sync with app.js, user.js, and headerReminders.html
     aOptions.showInvalidAuth = aRes.oujsOptions.showInvalidAuth;
diff --git a/routes.js b/routes.js
index 134b147d9..d4947e992 100644
--- a/routes.js
+++ b/routes.js
@@ -39,6 +39,8 @@ var settings = require('./models/settings.json');
 //--
 var limiter = process.env.LIMITER_STRING || settings.limiter;
 
+var lockdown = process.env.FORCE_BUSY_UPDATEURL_CHECK === 'true';
+
  // WATCHPOINT: ~60 second poll time in MongoDB
 var fudgeMin = 60;
 var fudgeSec = 6;
@@ -53,8 +55,49 @@ var installCapLimiter = rateLimit({
   windowMs: waitInstallCapMin * 60 * 1000, // n minutes for all stores
   max: 50, // limit each IP to n requests per windowMs for memory store or expireTimeMs for mongo store
   handler: function (aReq, aRes, aNext, aOptions) {
-    aRes.header('Retry-After', waitInstallCapMin * 60 + (isDev ? fudgeSec : fudgeMin));
-    aRes.status(429).send();
+    if (aReq.rateLimit.current < aReq.rateLimit.limit + 4) {
+      // Midddlware options
+      if (!aRes.oujsOptions) {
+        aRes.oujsOptions = {};
+      }
+
+      aRes.oujsOptions.showReminderInstallLimit = 4 - (aReq.rateLimit.current - aReq.rateLimit.limit);
+
+      aNext();
+    } else if (aReq.rateLimit.current < aReq.rateLimit.limit + 10) {
+      aRes.header('Retry-After', waitInstallCapMin * 60 + (isDev ? fudgeSec : fudgeMin));
+      statusCodePage(aReq, aRes, aNext, {
+        statusCode: 429,
+        statusMessage: 'Too many requests.',
+        suppressNavigation: true,
+        isCustomView: true,
+        statusData: {
+          isListView: true,
+          retryAfter: waitInstallCapMin * 60 + (isDev ? fudgeSec : fudgeMin)
+        }
+      });
+    } else if (aReq.rateLimit.current < aReq.rateLimit.limit + 15) {
+      aRes.header('Retry-After', waitInstallCapMin * 60 + (isDev ? fudgeSec : fudgeMin));
+      aRes.status(429).send('Too many requests. Please try again later');
+    } else if (aReq.rateLimit.current < aReq.rateLimit.limit + 20) {
+      aRes.header('Retry-After', waitInstallCapMin * 60 + (isDev ? fudgeSec : fudgeMin));
+      aRes.status(429).send();
+    } else {
+      cmd = (isPro && process.env.AUTOBAN ? process.env.AUTOBAN : 'echo SIMULATING INSTALL AUTOBAN') +
+        ' ' + aReq.connection.remoteAddress;
+
+      exec(cmd, function (aErr, aStdout, aStderr) {
+        if (aErr) {
+          console.error('FAIL INSTALL AUTOBAN', cmd);
+          // fallthrough
+        } else {
+          console.log('INSTALL AUTOBAN', aReq.connection.remoteAddress);
+          // fallthrough
+        }
+
+        aRes.connection.destroy();
+      });
+    }
   },
   skip: function (aReq, aRes) {
     var authedUser = aReq.session.user;
@@ -100,7 +143,7 @@ var installRateLimiter = rateLimit({
   skip: function (aReq, aRes) {
     var authedUser = aReq.session.user;
 
-    if (aReq.params.type === 'libs') {
+    if (aReq.params.type === 'libs' && !lockdown) {
       return true;
     }
 
@@ -277,15 +320,15 @@ var listCapLimiter = rateLimit({
       aRes.header('Retry-After', waitListCapMin * 60 + (isDev ? fudgeSec : fudgeMin));
       aRes.status(429).send();
     } else {
-      cmd = (isPro && process.env.AUTOBAN ? process.env.AUTOBAN : 'echo SIMULATING AUTOBAN') +
+      cmd = (isPro && process.env.AUTOBAN ? process.env.AUTOBAN : 'echo SIMULATING LIST AUTOBAN') +
         ' ' + aReq.connection.remoteAddress;
 
       exec(cmd, function (aErr, aStdout, aStderr) {
         if (aErr) {
-          console.error('FAIL AUTOBAN', cmd);
+          console.error('FAIL LIST AUTOBAN', cmd);
           // fallthrough
         } else {
-          console.log('AUTOBAN', aReq.connection.remoteAddress);
+          console.log('LIST AUTOBAN', aReq.connection.remoteAddress);
           // fallthrough
         }
 
diff --git a/views/includes/headerReminders.html b/views/includes/headerReminders.html
index 65cab24ca..954532dc9 100644
--- a/views/includes/headerReminders.html
+++ b/views/includes/headerReminders.html
@@ -57,6 +57,11 @@
     <p><i class="fa fa-fw fa-exclamation-triangle"></i> <b>WARNING:</b> You will reach your list limit in {{showReminderListLimit}} more requests.</p>
   </div>
 {{/showReminderListLimit}}
+{{#showReminderInstallLimit}}
+  <div class="alert alert-danger small fade in" role="alert">
+    <p><i class="fa fa-fw fa-exclamation-triangle"></i> <b>WARNING:</b> You will reach your install limit in {{showReminderListLimit}} more requests.</p>
+  </div>
+{{/showReminderInstallLimit}}
 {{#showSesssionNoExtend}}
   <div class="alert alert-danger alert-dismissible alert-autodismissible small fade in" role="alert">
     <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>