diff --git a/bin/clean-cache.js b/bin/clean-cache.js
index fb8fee6090ccd174ad51daec9f62de8ba3634b5c..eb1779386f531a1f1475165ac55ba94d2ae6a2d9 100644
--- a/bin/clean-cache.js
+++ b/bin/clean-cache.js
@@ -2,5 +2,5 @@ const fs = require('fs-extra');
 const os = require('os');
 
 (async () => {
-  await fs.remove(os.tmpdir() + '/renovate-cache-v1');
+  await fs.remove(os.tmpdir() + '/renovate');
 })();
diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index cb451f0e99530b0a2ee9cf6ff4029e414b5c6f53..90f96ae4ed18743a93d32e81a47da096756b1671 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -1,6 +1,8 @@
 const fs = require('fs-extra');
 const path = require('path');
 const upath = require('upath');
+const os = require('os');
+
 const npm = require('./npm');
 const lerna = require('./lerna');
 const yarn = require('./yarn');
@@ -305,10 +307,24 @@ async function getAdditionalFiles(config, packageFiles) {
   await module.exports.writeExistingFiles(config, packageFiles);
   await module.exports.writeUpdatedPackageFiles(config, packageFiles);
 
+  process.env.NPM_CONFIG_CACHE =
+    process.env.NPM_CONFIG_CACHE ||
+    upath.join(os.tmpdir(), '/renovate/npm-cache');
+  await fs.ensureDir(process.env.NPM_CONFIG_CACHE);
+  process.env.YARN_CACHE_FOLDER =
+    process.env.YARN_CACHE_FOLDER ||
+    upath.join(os.tmpdir(), '/renovate/yarn-cache');
+  await fs.ensureDir(process.env.YARN_CACHE_FOLDER);
+
   const env =
     config.global && config.global.exposeEnv
       ? process.env
-      : { HOME: process.env.HOME, PATH: process.env.PATH };
+      : {
+          HOME: process.env.HOME,
+          PATH: process.env.PATH,
+          NPM_CONFIG_CACHE: process.env.NPM_CONFIG_CACHE,
+          YARN_CACHE_FOLDER: process.env.YARN_CACHE_FOLDER,
+        };
   env.NODE_ENV = 'dev';
 
   let token = '';
diff --git a/lib/workers/global/cache.js b/lib/workers/global/cache.js
index 075d01cdced294e2b16ca51717dfd8776c071106..a782c335b411cb51e32e03a562dd53b66daa06d9 100644
--- a/lib/workers/global/cache.js
+++ b/lib/workers/global/cache.js
@@ -1,5 +1,6 @@
 const cacache = require('cacache/en');
 const os = require('os');
+const path = require('path');
 const { DateTime } = require('luxon');
 
 module.exports = {
@@ -10,8 +11,7 @@ function getKey(namespace, key) {
   return `${namespace}-${key}`;
 }
 
-const renovateCache =
-  (process.env.RENOVATE_TMPDIR || os.tmpdir()) + '/renovate-cache-v1';
+const renovateCache = path.join(os.tmpdir(), '/renovate/renovate-cache-v1');
 
 async function get(namespace, key) {
   try {
diff --git a/lib/workers/repository/index.js b/lib/workers/repository/index.js
index 6da864efce92aa07b0e7b214fabe7ad30c7d3ed7..95b8322080a9890deebf785a005eaaf5b30b87e6 100644
--- a/lib/workers/repository/index.js
+++ b/lib/workers/repository/index.js
@@ -1,6 +1,6 @@
 const fs = require('fs-extra');
 const os = require('os');
-const tmp = require('tmp-promise');
+const path = require('path');
 
 const { initRepo } = require('./init');
 const { ensureOnboardingPr } = require('./onboarding/pr');
@@ -19,16 +19,15 @@ async function renovateRepository(repoConfig) {
   logger.setMeta({ repository: config.repository });
   logger.info('Renovating repository');
   logger.trace({ config });
-  let tmpDir;
   try {
-    await fs.ensureDir(os.tmpdir());
-    if (config.localDir) {
-      await fs.ensureDir(config.localDir);
-    } else {
-      // Use an ephemeral directory if none configured
-      tmpDir = await tmp.dir({ unsafeCleanup: true });
-      config.localDir = tmpDir.path;
+    if (process.env.RENOVATE_TMPDIR) {
+      process.env.TMPDIR = process.env.RENOVATE_TMPDIR;
     }
+    const tmpDir = path.join(os.tmpdir(), '/renovate');
+    await fs.ensureDir(tmpDir);
+    config.localDir =
+      config.localDir || path.join(tmpDir, config.platform, config.repository);
+    await fs.ensureDir(config.localDir);
     logger.debug('Using localDir: ' + config.localDir);
     config = await initRepo(config);
     const { res, branches, branchList, packageFiles } = await processRepo(
@@ -41,8 +40,8 @@ async function renovateRepository(repoConfig) {
     return processResult(config, await handleError(config, err));
   } finally {
     platform.cleanRepo();
-    if (tmpDir) {
-      await tmpDir.cleanup();
+    if (config.localDir && !config.persistRepoData) {
+      await fs.remove(config.localDir);
     }
     logger.info('Finished repository');
   }
diff --git a/package.json b/package.json
index 8f6da21967434c084b3dfeebf7df481fabebcbd9..4408b2c46ecd9d11fd52fedd2dd7ffe400a4fc90 100644
--- a/package.json
+++ b/package.json
@@ -113,7 +113,6 @@
     "showdown": "1.8.6",
     "simple-git": "1.100.0",
     "slugify": "1.3.1",
-    "tmp-promise": "1.0.5",
     "traverse": "0.6.6",
     "upath": "1.1.0",
     "validator": "10.7.1",
@@ -136,7 +135,8 @@
     "mockdate": "2.0.2",
     "nock": "10.0.0",
     "prettier": "1.14.2",
-    "semantic-release": "15.9.15"
+    "semantic-release": "15.9.15",
+    "tmp-promise": "1.0.5"
   },
   "files": [
     "bin/config-validator.js",