diff --git a/lib/configuration.js b/lib/configuration.js
index 7682c5c0b713a8a400292af9c316d5cc20232519..b6523801135ed7dc8d4538efe43ed4cc5d83fc18 100644
--- a/lib/configuration.js
+++ b/lib/configuration.js
@@ -114,16 +114,13 @@ if (undefined !== process.env['NODE_EXTRA_CONFIG']) {
 // test environments are variations on local
 g_configs.test_json = JSON.parse(JSON.stringify(g_configs.local));
 g_configs.test_json.database = {
-  driver: "json",
-  // use a temporary path for testing
-  path: temp.path({suffix: '.db'})
+  driver: "json"
 };
 
 g_configs.test_mysql = JSON.parse(JSON.stringify(g_configs.local));
 g_configs.test_mysql.database = {
   driver: "mysql",
   user: "test",
-  database: "browserid_" + secrets.generate(6),
   create_schema: true
 };
 
diff --git a/lib/db.js b/lib/db.js
index fa05e1b640e59185816399a17f855f849ce31692..b71dcf8894660df2447c43bb07ac5e48d40ec21b 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -77,12 +77,21 @@ exports.open = function(cfg, cb) {
 
 
 exports.close = function(cb) {
+  checkReady();
   driver.close(function(err) {
     ready = false;
     if (cb) cb(err);
   });
 };
 
+exports.closeAndRemove = function(cb) {
+  checkReady();
+  driver.closeAndRemove(function(err) {
+    ready = false;
+    if (cb) cb(err);
+  });
+};
+
 // accepts a function that will be invoked once the database is ready for transactions.
 // this hook is important to pause the rest of application startup until async database
 // connection establishment is complete.
diff --git a/lib/db/json.js b/lib/db/json.js
index 9b393950ed17884c76fcdda1bdf750bcc2e08538..d26202992c7689a4ee84883e2f7aa5a1daad5bb8 100644
--- a/lib/db/json.js
+++ b/lib/db/json.js
@@ -52,8 +52,6 @@ const ESC = JSON.stringify;
 
 var dbPath = path.join(configuration.get('var_path'), "authdb.json");
 
-var drop_on_close = undefined;
-
 /* The JSON database. The structure is thus:
  *  [
  *    {
@@ -102,25 +100,19 @@ exports.open = function(cfg, cb) {
   }
   logger.debug("opening JSON database: " + dbPath);
 
-  if (cfg && cfg.drop_on_close) {
-    logger.debug("will remove database upon close");
-    drop_on_close = true;
-  }
-
   sync();
 
   setTimeout(cb, 0);
 };
 
-exports.close = function(cb) {
+exports.closeAndRemove = function(cb) {
   flush();
+  fs.unlink(dbPath, function(err) { cb(err === null ? undefined : err); });
+};
 
-  if (drop_on_close) {
-    drop_on_close = undefined;
-    fs.unlink(dbPath, function(err) { cb(err === null ? undefined : err); });
-  } else {
-    setTimeout(cb, 0);
-  }
+exports.close = function(cb) {
+  flush();
+  setTimeout(function() { cb(undefined) }, 0);
 };
 
 exports.emailKnown = function(email, cb) {
diff --git a/lib/db/mysql.js b/lib/db/mysql.js
index 08295f7f4c562a4c805018e2e559762d4102da17..97070a51cdd84d5bf83aa23a21616761c57ed6a0 100644
--- a/lib/db/mysql.js
+++ b/lib/db/mysql.js
@@ -65,9 +65,6 @@ logger = require('../logging.js').logger;
 
 var client = undefined;
 
-// may get defined at open() time causing a database to be dropped upon connection closing.
-var drop_on_close = undefined;
-
 // If you change these schemas, please notify <services-ops@mozilla.com>
 const schemas = [
   "CREATE TABLE IF NOT EXISTS user (" +
@@ -122,13 +119,9 @@ exports.open = function(cfg, cb) {
   var database = cfg.database;
   if (!database) database = "browserid";
 
-  // if the client specifies a name other than 'browserid', and specifies
-  // that we should drop the database on close, do it
-  if (database !== 'browserid' && cfg.drop_on_close) drop_on_close = database;
-
   // create the client
   function doConnect() {
-    logger.debug("connecting to database");
+    logger.debug("connecting to database: " + database);
     options.database = database;
     client = mysql.createClient(options);
     client.ping(function(err) {
@@ -185,22 +178,25 @@ exports.open = function(cfg, cb) {
 };
 
 exports.close = function(cb) {
-  function endConn() {
-    client.end(function(err) {
-      client = undefined;
-      if (err) logUnexpectedError(err);
-      if (cb) cb(err);
-    });
-  }
-  // when unit_test is specified at open time, we use a temporary database,
-  // and clean it up upon close.
-  if (drop_on_close) {
-    client.query("DROP DATABASE " + drop_on_close, function() {
-      endConn();
-    });
-  } else {
-    endConn();
+  client.end(function(err) {
+    client = undefined;
+    if (err) logUnexpectedError(err);
+    if (cb) cb(err);
+  });
+};
+
+exports.closeAndRemove = function(cb) {
+  var db_to_remove = client.database;
+
+  // don't let this happen if the name of the database is 'browserid',
+  // as a sanity check
+  if (db_to_remove === 'browserid') {
+    throw "dropping a database named 'browserid' is not allowed";
   }
+
+  client.query("DROP DATABASE " + db_to_remove, function(err) {
+    exports.close(cb);
+  });
 };
 
 exports.emailKnown = function(email, cb) {
@@ -258,11 +254,9 @@ exports.emailForVerificationSecret = function(secret, cb) {
 };
 
 exports.verificationSecretForEmail = function(email, cb) {
-  console.log("looking for " + email);
   client.query(
     "SELECT secret FROM staged WHERE email = ?", [ email ],
     function(err, rows) {
-      console.log("got", err, rows);
       if (err) logUnexpectedError(err);
       cb((rows && rows.length > 0) ? rows[0].secret : undefined);
     });
diff --git a/scripts/run_locally.js b/scripts/run_locally.js
index 344e09a1133cbfd1c61eba19e89af6fae49e4d7a..979a85aeca31bde6d1b5b92857df2efaaa758bd4 100755
--- a/scripts/run_locally.js
+++ b/scripts/run_locally.js
@@ -2,7 +2,10 @@
 
 const
 spawn = require('child_process').spawn,
-path = require('path');
+path = require('path'),
+config = require('../lib/configuration.js'),
+temp = require('temp'),
+secrets = require('../lib/secrets.js');
 
 exports.daemons = daemons = {};
 
@@ -41,6 +44,19 @@ process.env['BROWSERID_URL'] = 'http://' + HOST + ":10002";
 process.env['VERIFIER_URL'] = 'http://' + HOST + ":10000/verify";
 process.env['KEYSIGNER_URL'] = 'http://' + HOST + ":10003";
 
+// if the environment is a 'test_' environment, then we'll use an
+// ephemeral database
+if (config.get('env').substr(0,5) === 'test_') {
+  if (config.get('database').driver === 'mysql') {
+    process.env['MYSQL_DATABASE_NAME'] =
+      process.env['MYSQL_DATABASE_NAME'] ||"browserid_tmp_" + secrets.generate(6);
+    console.log("temp mysql database:", process.env['MYSQL_DATABASE_NAME']);
+  } else if (config.get('database').driver === 'json') {
+    process.env['JSON_DATABASE_PATH'] =  process.env['JSON_DATABASE_PATH'] || temp.path({suffix: '.db'});
+    console.log("temp json database:", process.env['JSON_DATABASE_PATH']);
+  }
+}
+
 function runDaemon(daemon, cb) {
   Object.keys(daemonsToRun[daemon]).forEach(function(ek) {
     process.env[ek] = daemonsToRun[daemon][ek];
@@ -53,8 +69,8 @@ function runDaemon(daemon, cb) {
       if (d.length === 0) return;
       console.log(daemon, '(' + p.pid + '):', d);
 
-      // when we find a line that looks like 'running on <url>' then we've fully
-      // started up and can run the next daemon.  see issue #556
+      // when we find a line that looks like 'running on <url>' then we've
+      // fully started up and can run the next daemon.  see issue #556
       if (cb && /^.*running on http:\/\/.*:[0-9]+$/.test(d)) {
         cb();
         cb = undefined;
diff --git a/tests/db-test.js b/tests/db-test.js
index 892319b46390218f6fb8651e063feed3c9fe9720..3fdba7a344b6b1bf1a15bbed3322c5aa18cc7ff5 100755
--- a/tests/db-test.js
+++ b/tests/db-test.js
@@ -290,6 +290,22 @@ suite.addBatch({
     },
     "should work": function(err) {
       assert.isUndefined(err);
+    },
+    "re-opening the database": {
+      topic: function() {
+        db.open(dbCfg, this.callback);
+      },
+      "works": function(r) {
+        assert.isUndefined(r);
+      },
+      "and then purging": {
+        topic: function() {
+          db.closeAndRemove(this.callback);
+        },
+        "works": function(r) {
+          assert.isUndefined(r);
+        }
+      }
     }
   }
 });
diff --git a/tests/lib/start-stop.js b/tests/lib/start-stop.js
index 7432041dd78601ebf0945b55899cde37d858785a..b9115f510f6a4acc6b6c88f842aa8f8679f8f51a 100644
--- a/tests/lib/start-stop.js
+++ b/tests/lib/start-stop.js
@@ -209,9 +209,9 @@ exports.addShutdownBatches = function(suite) {
 
   // clean up
   suite.addBatch({
-    "closing the database": {
+    "closing (and removing) the database": {
       topic: function() {
-        db.close(this.callback);
+        db.closeAndRemove(this.callback);
       },
       "should work": function(err) {
         assert.isUndefined(err);
diff --git a/tests/lib/test_env.js b/tests/lib/test_env.js
index 40f12e4c835347f7383c4e92e5d181752da33a10..664fe4c32f4638567ca219620fd03f5abfbdb473 100644
--- a/tests/lib/test_env.js
+++ b/tests/lib/test_env.js
@@ -44,5 +44,14 @@ if (undefined === process.env['NODE_ENV']) {
   process.env['NODE_ENV'] = 'test_json';
 } else if (process.env['NODE_ENV'].substr(0,5) !== 'test_') {
   console.log("(Woah.  Running tests without a test_ configuration.  Is this *really* what you want?)");
+  process.exit(1);
 }
 
+// if the environment is a 'test_' environment, then we'll use an
+// ephemeral database
+if (process.env['NODE_ENV'] === 'test_mysql') {
+  process.env['MYSQL_DATABASE_NAME'] = "browserid_tmp_" +
+    require('../../lib/secrets.js').generate(6);
+} else if (process.env['NODE_ENV'] === 'test_json') {
+  process.env['JSON_DATABASE_PATH'] = require('temp').path({suffix: '.db'});
+}