diff --git a/router/java/src/net/i2p/router/KeyManager.java b/router/java/src/net/i2p/router/KeyManager.java
index 0e0b4e5d6faee67e8866690d33da1dc140be538c..a0eddf9d31a9964e44e9b6be520fb0abb1daa409 100644
--- a/router/java/src/net/i2p/router/KeyManager.java
+++ b/router/java/src/net/i2p/router/KeyManager.java
@@ -8,10 +8,14 @@ package net.i2p.router;
  *
  */
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.InputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -42,7 +46,6 @@ public class KeyManager {
     private SigningPrivateKey _signingPrivateKey;
     private SigningPublicKey _signingPublicKey;
     private final Map<Hash, LeaseSetKeys> _leaseSetKeys; // Destination --> LeaseSetKeys
-    private final SynchronizeKeysJob _synchronizeJob;
     
     public final static String PROP_KEYDIR = "router.keyBackupDir";
     public final static String DEFAULT_KEYDIR = "keyBackup";
@@ -50,49 +53,38 @@ public class KeyManager {
     private final static String KEYFILE_PUBLIC_ENC = "publicEncryption.key";
     private final static String KEYFILE_PRIVATE_SIGNING = "privateSigning.key";
     private final static String KEYFILE_PUBLIC_SIGNING = "publicSigning.key";
-    // Doesn't seem like we need to periodically back up,
-    // since we don't store leaseSet keys,
-    // but for now just make it a long time.
-    private final static long DELAY = 7*24*60*60*1000;
     
     public KeyManager(RouterContext context) {
         _context = context;
         _log = _context.logManager().getLog(KeyManager.class);	
-        _synchronizeJob = new SynchronizeKeysJob();
         _leaseSetKeys = new ConcurrentHashMap();
     }
     
     public void startup() {
-        queueWrite();
+        // run inline so keys are loaded immediately
+        (new SynchronizeKeysJob()).runJob();
     }
     
-    /** Configure the router's private key */
-    public void setPrivateKey(PrivateKey key) { 
-        _privateKey = key; 
-        if (key != null)
-            queueWrite();
+    /**
+     *  Configure the router's keys.
+     *  @since 0.9.4 replace individual setters
+     */
+    public void setKeys(PublicKey key1, PrivateKey key2, SigningPublicKey key3, SigningPrivateKey key4) { 
+        synchronized(this) {
+            _publicKey = key1; 
+            _privateKey = key2; 
+            _signingPublicKey = key3; 
+            _signingPrivateKey = key4; 
+        }
+        queueWrite();
     }
+
     public PrivateKey getPrivateKey() { return _privateKey; }
-    /** Configure the router's public key */
-    public void setPublicKey(PublicKey key) { 
-        _publicKey = key; 
-        if (key != null)
-            queueWrite();
-    }
+
     public PublicKey getPublicKey() { return _publicKey; }
-    /** Configure the router's signing private key */
-    public void setSigningPrivateKey(SigningPrivateKey key) { 
-        _signingPrivateKey = key; 
-        if (key != null)
-            queueWrite();
-    }
+
     public SigningPrivateKey getSigningPrivateKey() { return _signingPrivateKey; }
-    /** Configure the router's signing public key */
-    public void setSigningPublicKey(SigningPublicKey key) { 
-        _signingPublicKey = key; 
-        if (key != null)
-            queueWrite();
-    }
+
     public SigningPublicKey getSigningPublicKey() { return _signingPublicKey; }
     
     public void registerKeys(Destination dest, SigningPrivateKey leaseRevocationPrivateKey, PrivateKey endpointDecryptionKey) {
@@ -102,15 +94,10 @@ public class KeyManager {
     }
    
     /**
-     *  Wait one second, as this will get called 4 times in quick succession
-     *  There is still a race here though, if a key is set while the sync job is running
+     *  Read/Write the router keys from/to disk
      */
     private void queueWrite() {
-        Clock cl = _context.clock();
-        JobQueue q = _context.jobQueue();
-        if ( (cl == null) || (q == null) ) return;
-        _synchronizeJob.getTiming().setStartAfter(cl.now() + 1000);
-        q.addJob(_synchronizeJob);
+        _context.jobQueue().addJob(new SynchronizeKeysJob());
     }
 
     public LeaseSetKeys unregisterKeys(Destination dest) {
@@ -122,27 +109,36 @@ public class KeyManager {
     public LeaseSetKeys getKeys(Destination dest) {
         return getKeys(dest.calculateHash());
     }
+
     public LeaseSetKeys getKeys(Hash dest) {
             return _leaseSetKeys.get(dest);
     }
     
+    /**
+     *  Read/Write the 4 files in keyBackup/
+     *  As of 0.9.4 this is run on-demand only, there's no need to
+     *  periodically sync.
+     *  Actually, there's little need for this at all.
+     *  If router.keys is corrupt, we should just make a new router identity,
+     *  there's no real reason to try so hard to recover our old keys.
+     */
     private class SynchronizeKeysJob extends JobImpl {
         public SynchronizeKeysJob() {
             super(KeyManager.this._context);
         }
+
         public void runJob() {
             String keyDir = getContext().getProperty(PROP_KEYDIR, DEFAULT_KEYDIR);
             File dir = new SecureDirectory(getContext().getRouterDir(), keyDir);
             if (!dir.exists())
                 dir.mkdirs();
             if (dir.exists() && dir.isDirectory() && dir.canRead() && dir.canWrite()) {
-                syncKeys(dir);
+                synchronized(KeyManager.this) {
+                    syncKeys(dir);
+                }
             } else {
                 _log.log(Log.CRIT, "Unable to synchronize keys in " + keyDir + " - permissions problem?");
             }
-
-            getTiming().setStartAfter(KeyManager.this._context.clock().now()+DELAY);
-            KeyManager.this._context.jobQueue().addJob(this);
         }
         
         private void syncKeys(File keyDir) {
@@ -152,7 +148,7 @@ public class KeyManager {
             syncVerificationKey(keyDir);
         }
 
-        private synchronized void syncPrivateKey(File keyDir) {
+        private void syncPrivateKey(File keyDir) {
             DataStructure ds;
             File keyFile = new File(keyDir, KEYFILE_PRIVATE_ENC);
             boolean exists = (_privateKey != null);
@@ -165,7 +161,7 @@ public class KeyManager {
                 _privateKey = (PrivateKey) readin;
         }
 
-        private synchronized void syncPublicKey(File keyDir) {
+        private void syncPublicKey(File keyDir) {
             DataStructure ds;
             File keyFile = new File(keyDir, KEYFILE_PUBLIC_ENC);
             boolean exists = (_publicKey != null);
@@ -178,7 +174,7 @@ public class KeyManager {
                 _publicKey = (PublicKey) readin;
         }
 
-        private synchronized void syncSigningKey(File keyDir) {
+        private void syncSigningKey(File keyDir) {
             DataStructure ds;
             File keyFile = new File(keyDir, KEYFILE_PRIVATE_SIGNING);
             boolean exists = (_signingPrivateKey != null);
@@ -191,7 +187,7 @@ public class KeyManager {
                 _signingPrivateKey = (SigningPrivateKey) readin;
         }
 
-        private synchronized void syncVerificationKey(File keyDir) {
+        private void syncVerificationKey(File keyDir) {
             DataStructure ds;
             File keyFile = new File(keyDir, KEYFILE_PUBLIC_SIGNING);
             boolean exists = (_signingPublicKey != null);
@@ -205,16 +201,16 @@ public class KeyManager {
         }
 
         private DataStructure syncKey(File keyFile, DataStructure structure, boolean exists) {
-            FileOutputStream out = null;
-            FileInputStream in = null;
+            OutputStream out = null;
+            InputStream in = null;
             try {
                 if (exists) {
-                    out = new SecureFileOutputStream(keyFile);
+                    out = new BufferedOutputStream(new SecureFileOutputStream(keyFile));
                     structure.writeBytes(out);
                     return structure;
                 } else {
                     if (keyFile.exists()) {
-                        in = new FileInputStream(keyFile);
+                        in = new BufferedInputStream(new FileInputStream(keyFile));
                         structure.readBytes(in);
                         return structure;
                     } else {
diff --git a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java
index 6bd9d3f08b9a3ea642c3a8cf8f81c970a9b7acad..3aebb3b51e8a38b721a5f595623ccc8314d5897a 100644
--- a/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java
@@ -8,9 +8,11 @@ package net.i2p.router.startup;
  *
  */
 
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.util.Properties;
 
 import net.i2p.data.Certificate;
@@ -50,12 +52,25 @@ public class CreateRouterInfoJob extends JobImpl {
     }
     
     /**
-     *  Caller must hold Router.routerInfoFileLock
+     *  Writes 6 files: router.info (standard RI format),
+     *  router,keys, and 4 individual key files under keyBackup/
+     *
+     *  router.keys file format: Note that this is NOT the
+     *  same "eepPriv.dat" format used by the client code.
+     *<pre>
+     *   - Private key (256 bytes)
+     *   - Signing Private key (20 bytes)
+     *   - Public key (256 bytes)
+     *   - Signing Public key (128 bytes)
+     *  Total 660 bytes
+     *</pre>
+     *
+     *  Caller must hold Router.routerInfoFileLock.
      */
     RouterInfo createRouterInfo() {
         RouterInfo info = new RouterInfo();
-        FileOutputStream fos1 = null;
-        FileOutputStream fos2 = null;
+        OutputStream fos1 = null;
+        OutputStream fos2 = null;
         try {
             info.setAddresses(getContext().commSystem().createAddresses());
             Properties stats = getContext().statPublisher().publishStatistics();
@@ -89,21 +104,18 @@ public class CreateRouterInfoJob extends JobImpl {
             
             String infoFilename = getContext().getProperty(Router.PROP_INFO_FILENAME, Router.PROP_INFO_FILENAME_DEFAULT);
             File ifile = new File(getContext().getRouterDir(), infoFilename);
-            fos1 = new SecureFileOutputStream(ifile);
+            fos1 = new BufferedOutputStream(new SecureFileOutputStream(ifile));
             info.writeBytes(fos1);
             
             String keyFilename = getContext().getProperty(Router.PROP_KEYS_FILENAME, Router.PROP_KEYS_FILENAME_DEFAULT);
             File kfile = new File(getContext().getRouterDir(), keyFilename);
-            fos2 = new SecureFileOutputStream(kfile);
+            fos2 = new BufferedOutputStream(new SecureFileOutputStream(kfile));
             privkey.writeBytes(fos2);
             signingPrivKey.writeBytes(fos2);
             pubkey.writeBytes(fos2);
             signingPubKey.writeBytes(fos2);
             
-            getContext().keyManager().setSigningPrivateKey(signingPrivKey);
-            getContext().keyManager().setSigningPublicKey(signingPubKey);
-            getContext().keyManager().setPrivateKey(privkey);
-            getContext().keyManager().setPublicKey(pubkey);
+            getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
             
             _log.info("Router info created and stored at " + ifile.getAbsolutePath() + " with private keys stored at " + kfile.getAbsolutePath() + " [" + info + "]");
         } catch (DataFormatException dfe) {
diff --git a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
index 392a8b3c8b668ff5f0aa0a2783ade1d05bb7c6e4..e937cca8c33d61362381dcb2f6d37e69b851668c 100644
--- a/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
+++ b/router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java
@@ -8,8 +8,10 @@ package net.i2p.router.startup;
  *
  */
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.InputStream;
 import java.io.IOException;
 
 import net.i2p.data.DataFormatException;
@@ -64,8 +66,8 @@ public class LoadRouterInfoJob extends JobImpl {
         if (rkf.exists())
             _keysExist = true;
         
-        FileInputStream fis1 = null;
-        FileInputStream fis2 = null;
+        InputStream fis1 = null;
+        InputStream fis2 = null;
         try {
             // if we have a routerinfo but no keys, things go bad in a hurry:
             // CRIT   ...rkdb.PublishLocalRouterInfoJob: Internal error - signing private key not known?  rescheduling publish for 30s
@@ -74,7 +76,7 @@ public class LoadRouterInfoJob extends JobImpl {
             // at net.i2p.router.transport.udp.PacketBuilder.buildSessionConfirmedPacket(PacketBuilder.java:574)
             // so pretend the RI isn't there if there is no keyfile
             if (_infoExists && _keysExist) {
-                fis1 = new FileInputStream(rif);
+                fis1 = new BufferedInputStream(new FileInputStream(rif));
                 info = new RouterInfo();
                 info.readBytes(fis1);
                 // Catch this here before it all gets worse
@@ -86,7 +88,7 @@ public class LoadRouterInfoJob extends JobImpl {
             }
             
             if (_keysExist) {
-                fis2 = new FileInputStream(rkf);
+                fis2 = new BufferedInputStream(new FileInputStream(rkf));
                 PrivateKey privkey = new PrivateKey();
                 privkey.readBytes(fis2);
                 SigningPrivateKey signingPrivKey = new SigningPrivateKey();
@@ -96,10 +98,7 @@ public class LoadRouterInfoJob extends JobImpl {
                 SigningPublicKey signingPubKey = new SigningPublicKey();
                 signingPubKey.readBytes(fis2);
                 
-                getContext().keyManager().setPrivateKey(privkey);
-                getContext().keyManager().setSigningPrivateKey(signingPrivKey);
-                getContext().keyManager().setPublicKey(pubkey); //info.getIdentity().getPublicKey());
-                getContext().keyManager().setSigningPublicKey(signingPubKey); // info.getIdentity().getSigningPublicKey());
+                getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
             }
         } catch (IOException ioe) {
             _log.log(Log.CRIT, "Error reading the router info from " + rif.getAbsolutePath() + " and the keys from " + rkf.getAbsolutePath(), ioe);