diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts
index 1f9941c2c22a47f5d82f1d11c59e598171d6c8c6..79a0f256f9c7bdd9535604c55fbea07b837c5bc1 100644
--- a/lib/config/definitions.ts
+++ b/lib/config/definitions.ts
@@ -971,6 +971,13 @@ const options: RenovateOptions[] = [
     type: 'boolean',
     default: false,
   },
+  {
+    name: 'stabilityDays',
+    description:
+      'Number of days required before a new release is considered to be stabilized.',
+    type: 'integer',
+    default: 0,
+  },
   {
     name: 'prCreation',
     description: 'When to create the PR for a branch.',
diff --git a/lib/workers/branch/index.js b/lib/workers/branch/index.js
index cd382564b9788cfe421dea7340527614f498f7db..562c230a1189b287f2912b3b350d5e3df1cbe03c 100644
--- a/lib/workers/branch/index.js
+++ b/lib/workers/branch/index.js
@@ -7,7 +7,7 @@ const { getAdditionalFiles } = require('../../manager/npm/post-update');
 const { commitFilesToBranch } = require('./commit');
 const { getParentBranch } = require('./parent');
 const { tryBranchAutomerge } = require('./automerge');
-const { setUnpublishable } = require('./status-checks');
+const { setStability, setUnpublishable } = require('./status-checks');
 const { prAlreadyExisted } = require('./check-existing');
 const prWorker = require('../pr');
 const { appName, appSlug } = require('../../config/app-strings');
@@ -188,6 +188,48 @@ async function processBranch(branchConfig, prHourlyLimitReached, packageFiles) {
       );
       return 'pending';
     }
+
+    if (
+      config.upgrades.some(
+        upgrade => upgrade.stabilityDays && upgrade.releaseTimestamp
+      )
+    ) {
+      // Only set a stability status check if one or more of the updates contain
+      // both a stabilityDays setting and a releaseTimestamp
+      config.stabilityStatus = 'success';
+      // Default to 'success' but set 'pending' if any update is pending
+      const oneDay = 24 * 60 * 60 * 1000;
+      for (const upgrade of config.upgrades) {
+        if (upgrade.stabilityDays && upgrade.releaseTimestamp) {
+          const daysElapsed = Math.floor(
+            (new Date().getTime() -
+              new Date(upgrade.releaseTimestamp).getTime()) /
+              oneDay
+          );
+          if (daysElapsed < upgrade.stabilityDays) {
+            logger.debug(
+              {
+                depName: upgrade.depName,
+                daysElapsed,
+                stabilityDays: upgrade.stabilityDays,
+              },
+              'Update has not passed stability days'
+            );
+            config.stabilityStatus = 'pending';
+          }
+        }
+      }
+      // Don't create a branch if we know it will be status 'pending'
+      if (
+        !branchExists &&
+        config.stabilityStatus === 'pending' &&
+        ['not-pending', 'status-success'].includes(config.prCreation)
+      ) {
+        logger.info('Skipping branch creation due to stability days not met');
+        return 'pending';
+      }
+    }
+
     // istanbul ignore if
     if (masterIssueCheck === 'rebase' || config.masterIssueRebaseAllOpen) {
       logger.info('Manual rebase requested via master issue');
@@ -269,6 +311,7 @@ async function processBranch(branchConfig, prHourlyLimitReached, packageFiles) {
     }
 
     // Set branch statuses
+    await setStability(config);
     await setUnpublishable(config);
 
     // Try to automerge branch and finish if successful, but only if branch already existed before this run
diff --git a/lib/workers/branch/status-checks.js b/lib/workers/branch/status-checks.js
index 061fdd28c18b2dd01b3db0897eb6dd0588a21594..f7069470aaa29736078a9944a1317686223ae915 100644
--- a/lib/workers/branch/status-checks.js
+++ b/lib/workers/branch/status-checks.js
@@ -2,6 +2,7 @@ const { logger } = require('../../logger');
 const { appSlug, urls } = require('../../config/app-strings');
 
 module.exports = {
+  setStability,
   setUnpublishable,
 };
 
@@ -25,6 +26,23 @@ async function setStatusCheck(branchName, context, description, state) {
   }
 }
 
+async function setStability(config) {
+  if (!config.stabilityStatus) {
+    return;
+  }
+  const context = `${appSlug}/stability-days`;
+  const description =
+    config.stabilityStatus === 'success'
+      ? 'Updates have met stability days requirement'
+      : 'Updates have not met stability days requirement';
+  await setStatusCheck(
+    config.branchName,
+    context,
+    description,
+    config.stabilityStatus
+  );
+}
+
 async function setUnpublishable(config) {
   if (!config.unpublishSafe) {
     return;
diff --git a/renovate-schema.json b/renovate-schema.json
index ec947d2b18e49cc9b045dc5c2493b58dc8833055..1cebd4b269e3c8b1a1691fa7ee121e9cb313be99 100644
--- a/renovate-schema.json
+++ b/renovate-schema.json
@@ -592,6 +592,11 @@
       "type": "boolean",
       "default": false
     },
+    "stabilityDays": {
+      "description": "Number of days required before a new release is considered to be stabilized.",
+      "type": "integer",
+      "default": 0
+    },
     "prCreation": {
       "description": "When to create the PR for a branch.",
       "type": "string",
diff --git a/test/workers/branch/index.spec.js b/test/workers/branch/index.spec.js
index 5027e424c3f2ee8b7aa7ffe5b7bed3e0a51c1be6..30dd138bd33810ffa452cedeb8bd52b0931c45c6 100644
--- a/test/workers/branch/index.spec.js
+++ b/test/workers/branch/index.spec.js
@@ -75,6 +75,18 @@ describe('workers/branch', () => {
       const res = await branchWorker.processBranch(config);
       expect(res).toEqual('pending');
     });
+    it('skips branch if not stabilityDays not met', async () => {
+      schedule.isScheduledNow.mockReturnValueOnce(true);
+      config.prCreation = 'not-pending';
+      config.upgrades = [
+        {
+          releaseTimestamp: '2099-12-31',
+          stabilityDays: 1,
+        },
+      ];
+      const res = await branchWorker.processBranch(config);
+      expect(res).toEqual('pending');
+    });
     it('processes branch if not scheduled but updating out of schedule', async () => {
       schedule.isScheduledNow.mockReturnValueOnce(false);
       config.updateNotScheduled = true;
diff --git a/test/workers/branch/status-checks.spec.js b/test/workers/branch/status-checks.spec.js
index 17fec24c5fa5372bb5c2ae19f61e326ff3bbe245..2c69ac7159732c30df74d5cb1d00b2736c4b2621 100644
--- a/test/workers/branch/status-checks.spec.js
+++ b/test/workers/branch/status-checks.spec.js
@@ -1,4 +1,5 @@
 const {
+  setStability,
   setUnpublishable,
 } = require('../../../lib/workers/branch/status-checks');
 const defaultConfig = require('../../../lib/config/defaults').getConfig();
@@ -7,6 +8,33 @@ const defaultConfig = require('../../../lib/config/defaults').getConfig();
 const platform = global.platform;
 
 describe('workers/branch/status-checks', () => {
+  describe('setStability', () => {
+    let config;
+    beforeEach(() => {
+      config = {
+        ...defaultConfig,
+      };
+    });
+    afterEach(() => {
+      jest.resetAllMocks();
+    });
+    it('returns if not configured', async () => {
+      await setStability(config);
+      expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(0);
+    });
+    it('sets status pending', async () => {
+      config.stabilityStatus = 'pending';
+      await setStability(config);
+      expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
+      expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
+    });
+    it('sets status success', async () => {
+      config.stabilityStatus = 'success';
+      await setStability(config);
+      expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
+      expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
+    });
+  });
   describe('setUnpublishable', () => {
     let config;
     beforeEach(() => {
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index 3e2d16bdf23eb9e05d47a49016c8032be8173528..b9b9c8d233b6022b1e9c1445f386cbd3e2632f11 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -1083,6 +1083,20 @@ By default, Renovate won't distinguish between "patch" (e.g. 1.0.x) and "minor"
 
 Set this to true if you wish to receive one PR for every separate major version upgrade of a dependency. e.g. if you are on webpack@v1 currently then default behaviour is a PR for upgrading to webpack@v3 and not for webpack@v2. If this setting is true then you would get one PR for webpack@v2 and one for webpack@v3.
 
+## stabilityDays
+
+If this is set to a non-zero value, and an update has a release date/timestamp available, then Renovate will check if the configured "stability days" have elapsed. If the days since the release is less than the configured stability days then a "pending" status check will be added to the branch. If enough days have passed then a passing status check will be added.
+
+There are a couple of uses for this:
+
+#### Suppress branch/PR creation for X days
+
+If you combine `stabilityDays=3` and `prCreation="not-pending"` then Renovate will hold back from creating branches until 3 or more days have elapsed since the version was released. It's recommended that you enable `masterIssue=true` so you don't lose visibility of these pending PRs.
+
+#### Await X days before Automerging
+
+If you have both `automerge` as well as `stabilityDays` enabled, it means that PRs will be created immediately but automerging will be delayed until X days have passed. This works because Renovate will add a "renovate/stability-days" pending status check to each branch/PR and that pending check will prevent the branch going green to automerge.
+
 ## statusCheckVerify
 
 This feature is added for people migrating from alternative services who are used to seeing a "verify" status check on PRs. If you'd like to use this then go ahead, but otherwise it's more secure to look for Renovate's [GPG Verified Commits](https://github.com/blog/2144-gpg-signature-verification) instead, because those cannot be spoofed by any other person or service (unlike status checks).