diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js
index 9f8840e5b63cb7e98d6ea7dc63eea1347e3b7492..831736a17c70735128fb70b5ef09ddfe2870192e 100644
--- a/browserid/lib/wsapi.js
+++ b/browserid/lib/wsapi.js
@@ -139,35 +139,49 @@ function setup(app) {
     }
 
     // bcrypt the password
-    stageParams['hash'] = bcrypt.encrypt_sync(stageParams.pass, bcrypt.gen_salt_sync(10));
-
-    try {
-      // upon success, stage_user returns a secret (that'll get baked into a url
-      // and given to the user), on failure it throws
-      db.stageUser(stageParams, function(secret) {
-        // store the email being registered in the session data
-        if (!req.session) req.session = {};
-
-        // store inside the session the details of this pending verification
-        req.session.pendingVerification = {
-          email: stageParams.email,
-          hash: stageParams.hash // we must store both email and password to handle the case where
-          // a user re-creates an account - specifically, registration status
-          // must ensure the new credentials work to properly verify that
-          // the user has clicked throught the email link. note, this salted, bcrypted
-          // representation of a user's password will get thrust into an encrypted cookie
-          // served over an encrypted (SSL) session.  guten, yah.
-        };
+    bcrypt.gen_salt(10, function (err, salt) {
+      if (err) {
+        winston.error("error generating salt with bcrypt: " + err);
+        return resp.json(false);
+      }
 
-        resp.json(true);
+      bcrypt.encrypt(stageParams.pass, salt, function(err, hash) {
+        if (err) {
+          winston.error("error generating password hash with bcrypt: " + err);
+          return resp.json(false);
+        }
 
-        // let's now kick out a verification email!
-        email.sendVerificationEmail(stageParams.email, stageParams.site, secret);
+        stageParams['hash'] = hash;
+
+        try {
+          // upon success, stage_user returns a secret (that'll get baked into a url
+          // and given to the user), on failure it throws
+          db.stageUser(stageParams, function(secret) {
+            // store the email being registered in the session data
+            if (!req.session) req.session = {};
+
+            // store inside the session the details of this pending verification
+            req.session.pendingVerification = {
+              email: stageParams.email,
+              hash: stageParams.hash // we must store both email and password to handle the case where
+              // a user re-creates an account - specifically, registration status
+              // must ensure the new credentials work to properly verify that
+              // the user has clicked throught the email link. note, this salted, bcrypted
+              // representation of a user's password will get thrust into an encrypted cookie
+              // served over an encrypted (SSL) session.  guten, yah.
+            };
+
+            resp.json(true);
+
+            // let's now kick out a verification email!
+            email.sendVerificationEmail(stageParams.email, stageParams.site, secret);
+          });
+        } catch(e) {
+          // we should differentiate tween' 400 and 500 here.
+          httputils.badRequest(resp, e.toString());
+        }
       });
-    } catch(e) {
-      // we should differentiate tween' 400 and 500 here.
-      httputils.badRequest(resp, e.toString());
-    }
+    });
   });
 
   app.get('/wsapi/registration_status', function(req, resp) {
@@ -217,17 +231,23 @@ function setup(app) {
 
   app.post('/wsapi/authenticate_user', checkParams(["email", "pass"]), function(req, resp) {
     db.checkAuth(req.body.email, function(hash) {
-      var success =
-        (typeof hash === 'string' &&
-         typeof req.body.pass === 'string' && 
-         bcrypt.compare_sync(req.body.pass, hash));
-
-      if (success) {
-        if (!req.session) req.session = {};
-        req.session.authenticatedUser = req.body.email;
+      if (typeof hash !== 'string' ||
+          typeof req.body.pass !== 'string')
+      {
+        return resp.json(false);
       }
 
-      resp.json(success);
+      bcrypt.compare(req.body.pass, hash, function (err, success) {
+        if (err) {
+          winston.warn("error comparing passwords with bcrypt: " + err);
+          success = false;
+        }
+        if (success) {
+          if (!req.session) req.session = {};
+          req.session.authenticatedUser = req.body.email;
+        }
+        resp.json(success);
+      });
     });
   });
 
diff --git a/package.json b/package.json
index 0e8e91a19c7337e27e31b1b00ebacd9f14ab41c6..da47ac2b00cdb47275b04eab1f7fcfd2ca9f2cc7 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
     , "nodemailer": "0.1.18"
     , "mustache": "0.3.1-dev"
     , "vows": "0.5.8"
-    , "bcrypt": "0.2.3"
+    , "bcrypt": "0.2.4"
     , "ejs": "0.4.3"
     , "temp": "0.2.0"
     , "express-csrf": "0.3.2"
diff --git a/performance/run.js b/performance/run.js
index c75522a8b5006a057ced03077d0808b1318f227c..fea7840d007065bffe5d4f0721b24240b8b4a916 100755
--- a/performance/run.js
+++ b/performance/run.js
@@ -280,7 +280,7 @@ function poll() {
 }
 
 // always start out by creating a bunch of users
-var NUM_INITIAL_USERS = 50;
+var NUM_INITIAL_USERS = 100;
 
 // if an explicit target was specified, let's output what that means
 // in understandable terms