diff --git a/jsconfig.json b/jsconfig.json
index 9e26dfeeb6e641a33dae4961196235bdb965b21b..9cb1d84b57165b066626eeca2e1428d98a8a2e26 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1 +1,3 @@
-{}
\ No newline at end of file
+{
+  "compileOnSave": false
+}
diff --git a/www/js/config.js b/www/js/config.js
index 0027636ef2017dcd29ec16061c4429d103dbd6b8..47f6eb71dda8eec252d41f26426775af37cd8865 100644
--- a/www/js/config.js
+++ b/www/js/config.js
@@ -15,7 +15,7 @@ angular.module("cesium.config", [])
 	"fallbackLanguage": "en",
 	"rememberMe": true,
 	"showUDHistory": true,
-	"timeout": 40000,
+	"timeout": 3000,
 	"timeWarningExpireMembership": 5184000,
 	"timeWarningExpire": 7776000,
 	"keepAuthIdle": 600,
@@ -124,4 +124,4 @@ angular.module("cesium.config", [])
 	"newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new"
 })
 
-;
\ No newline at end of file
+;
diff --git a/www/js/entities/peer.js b/www/js/entities/peer.js
index 91e7b6d131d4cf95804d9e4de425e49b5c8e672a..6a2e1fbbaadb869646c6e4fa03b46d74d06b0486 100644
--- a/www/js/entities/peer.js
+++ b/www/js/entities/peer.js
@@ -120,7 +120,7 @@ Peer.prototype.getIPv6 = function() {
 
 Peer.prototype.getPort = function() {
   var bma = this.bma || this.getBMA();
-  return bma.port ? bma.port : null;
+  return bma.port ? parseInt(bma.port) : null;
 };
 
 Peer.prototype.getHost = function(getHost) {
diff --git a/www/js/platform.js b/www/js/platform.js
index ae21c0b969a49e2ce58b9f4779765ab82352662c..39813ca2b962fe85a67aee1d6404245942ba8199 100644
--- a/www/js/platform.js
+++ b/www/js/platform.js
@@ -102,15 +102,14 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
 
   .factory('csPlatform', function (ionicReady, $rootScope, $q, $state, $translate, $timeout, $ionicHistory, $window,
                                    UIUtils, Modals, BMA, Device,
-                                   csHttp, csConfig, csCache, csSettings, csCurrency, csWallet) {
+                                   csHttp, csConfig, csCache, csSettings, csNetwork, csCurrency, csWallet) {
 
     'ngInject';
     var
-      fallbackNodeIndex = 0,
-      defaultSettingsNode,
+      checkBmaNodeAliveCounter = 0,
       started = false,
       startPromise,
-      listeners,
+      listeners = [],
       removeChangeStateListener;
 
     // Fix csConfig values
@@ -146,58 +145,120 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
     function checkBmaNodeAlive(alive) {
       if (alive) return true;
 
-      // Remember the default node
-      defaultSettingsNode = defaultSettingsNode || csSettings.data.node;
+      checkBmaNodeAliveCounter++;
+      if (checkBmaNodeAliveCounter > 3)  throw 'ERROR.CHECK_NETWORK_CONNECTION'; // Avoid infinite loop
 
-      var fallbackNode = csSettings.data.fallbackNodes && fallbackNodeIndex < csSettings.data.fallbackNodes.length && csSettings.data.fallbackNodes[fallbackNodeIndex++];
-      if (!fallbackNode) {
-        throw 'ERROR.CHECK_NETWORK_CONNECTION';
-      }
-      var newServer = fallbackNode.host + ((!fallbackNode.port && fallbackNode.port != 80 && fallbackNode.port != 443) ? (':' + fallbackNode.port) : '');
+      return BMA.filterAliveNodes(csSettings.data.fallbackNodes, Math.min(csConfig.timeout, 3000)/*3s max*/)
+        .then(function (fallbackNodes) {
+          if (!fallbackNodes.length) {
+            throw 'ERROR.CHECK_NETWORK_CONNECTION';
+          }
+          var randomIndex = Math.floor(Math.random() * fallbackNodes.length);
+          var fallbackNode = fallbackNodes[randomIndex];
+          return fallbackNode;
+        })
+        .then(function (fallbackNode) {
 
-      // Skip is same as actual node
-      if (BMA.node.same(fallbackNode)) {
-        console.debug('[platform] Skipping fallback node [{0}]: same as actual node'.format(newServer));
-        return checkBmaNodeAlive(); // loop (= go to next node)
-      }
+          // Not expert mode: continue with the fallback node
+          if (!csSettings.data.expertMode) {
+            console.info("[platform] Switching to fallback node: {}".format(fallbackNode.server));
+            return fallbackNode;
+          }
 
-      // Try to get summary
-      return csHttp.get(fallbackNode.host, fallbackNode.port, '/node/summary', fallbackNode.port == 443 || BMA.node.forceUseSsl)()
-        .catch(function (err) {
-          console.error('[platform] Could not reach fallback node [{0}]: skipping'.format(newServer));
-          // silent, but return no result (will loop to the next fallback node)
-        })
-        .then(function (res) {
-          if (!res) return checkBmaNodeAlive(); // Loop
+          // If expert mode: ask user to confirm, before switching to fallback node
+          var confirmMsgParams = {old: BMA.server, new: fallbackNode.server};
 
           // Force to show port/ssl, if this is the only difference
-          var messageParam = {old: BMA.server, new: newServer};
-          if (messageParam.old === messageParam.new) {
+          if (confirmMsgParams.old === confirmMsgParams.new) {
             if (BMA.port != fallbackNode.port) {
-              messageParam.new += ':' + fallbackNode.port;
+              confirmMsgParams.new += ':' + fallbackNode.port;
             } else if (BMA.useSsl == false && (fallbackNode.useSsl || fallbackNode.port == 443)) {
-              messageParam.new += ' (SSL)';
+              confirmMsgParams.new += ' (SSL)';
             }
           }
 
-          return $translate('CONFIRM.USE_FALLBACK_NODE', messageParam)
-            .then(function (msg) {
-              return UIUtils.alert.confirm(msg);
-            })
+          return $translate('CONFIRM.USE_FALLBACK_NODE', confirmMsgParams)
+            .then(UIUtils.alert.confirm)
             .then(function (confirm) {
-              if (!confirm) return;
+              if (!confirm) return; // Stop
+              return fallbackNode;
+            });
+        })
+        .then(function (fallbackNode) {
+          if (!fallbackNode) return; // Skip
+
+          // Only change BMA node in settings
+          csSettings.data.node = fallbackNode;
+
+          // Add a marker, for UI
+          csSettings.data.node.temporary = true;
 
+          csHttp.cache.clear();
+
+          // loop
+          return BMA.copy(fallbackNode)
+            .then(checkBmaNodeAlive);
+        });
+    }
+
+    // Make sure the BMA node is synchronized (is on the main consensus block)
+    function checkBmaNodeSynchronized() {
+      var now = Date.now();
+      console.info("[platform] Checking if node is synchronized...");
+
+      csNetwork.getSynchronizedBmaPeers(BMA, {
+        timeout:  Math.min(csConfig.timeout, 3000 /*3s max*/)
+      })
+        .then(function(peers) {
+          console.info("[platform] Network scanned in {0}ms, {1} peers (UP and synchronized) found".format(Date.now() - now, peers.length));
+
+          // TODO: store sync peers in storage ?
+
+          // Try to find the current peer in the list of synchronized peers
+          var synchronized = _.some(peers, function(peer) {
+            return BMA.node.same({
+              host: peer.getHost(),
+              port: peer.getPort(),
+              useSsl: peer.isSsl()
+            });
+          });
+
+          // OK (BMA node is sync): continue
+          if (synchronized) {
+            console.info("[platform] Default peer [{0}] is well synchronized.".format(BMA.server));
+            return true;
+          }
+
+          var consensusBlockNumber = peers.length ? peers[0].currentNumber : undefined;
+          return csCurrency.blockchain.current()
+            .then(function(block) {
+
+              // Only one block late: keep current node
+              if (Math.abs(block.number - consensusBlockNumber) <= 2) {
+                console.info("[platform] Keep BMA node [{0}], as current block #{1} is closed to consensus block #{2}".format(BMA.server, block.number, consensusBlockNumber));
+                return true;
+              }
+
+              // If Expert mode: ask user to select a node
+              if (csSettings.data.expertMode) {
+                return selectBmaNode();
+              }
+
+              var randomIndex = Math.floor(Math.random() * peers.length);
+              var randomPeer = peers[randomIndex];
+              var node = {
+                host: randomPeer.getHost(),
+                port: randomPeer.getPort(),
+                useSsl: randomPeer.isSsl()
+              };
+              console.info("[platform] Randomly selected peer {0}".format(randomPeer.server));
               // Only change BMA node in settings
-              csSettings.data.node = fallbackNode;
+              csSettings.data.node = node;
 
               // Add a marker, for UI
               csSettings.data.node.temporary = true;
 
-              csHttp.cache.clear();
-
-              // loop
-              return BMA.copy(fallbackNode)
-                .then(checkBmaNodeAlive);
+              return BMA.copy(node);
             });
         });
     }
@@ -263,10 +324,10 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
 
 
     function addListeners() {
-      listeners = [
-        // Listen if node changed
+      // Listen if node changed
+      listeners.push(
         BMA.api.node.on.restart($rootScope, restart, this)
-      ];
+      );
     }
 
     function removeListeners() {
@@ -294,7 +355,6 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
       // Avoid change state
       disableChangeState();
 
-
       // We use 'ionicReady()' instead of '$ionicPlatform.ready()', because this one is callable many times
       startPromise = ionicReady()
 
@@ -308,9 +368,10 @@ angular.module('cesium.platform', ['ngIdle', 'cesium.config', 'cesium.services']
 
         // Load BMA
         .then(function(){
+          checkBmaNodeAliveCounter = 0;
           return BMA.ready()
             .then(checkBmaNodeAlive)
-            .then(selectBmaNode);
+            .then(checkBmaNodeSynchronized);
         })
 
         // Load currency
diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js
index ffacc98f31e8b2d258929557bdfc0f5e12ebea9f..edf1cb67c1d4d5d46579407de5bff9a1d824ef8f 100644
--- a/www/js/services/bma-services.js
+++ b/www/js/services/bma-services.js
@@ -234,13 +234,13 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
       };
     }
 
-    that.isAlive = function(node) {
+    that.isAlive = function(node, timeout) {
       node = node || that;
       // WARN:
       //  - Cannot use previous get() function, because
       //    node can be !=that, or not be started yet
       //  - Do NOT use cache here
-      return csHttp.get(node.host, node.port, '/node/summary', node.useSsl)()
+      return csHttp.get(node.host, node.port, '/node/summary', node.useSsl || that.forceUseSsl, timeout)()
         .then(function(json) {
           var software = json && json.duniter && json.duniter.software;
           var isCompatible = true;
@@ -259,7 +259,7 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
           return isCompatible;
         })
         .catch(function() {
-          return false;
+          return false; // Unreacheable
         });
     };
 
@@ -382,6 +382,31 @@ angular.module('cesium.bma.services', ['ngApi', 'cesium.http.services', 'cesium.
         });
     };
 
+    that.filterAliveNodes = function(fallbackNodes, timeout) {
+      var fallbackNodes = _.filter(fallbackNodes || [], function(node) {
+        node.server = node.server || node.host + ((!node.port && node.port != 80 && node.port != 443) ? (':' + node.port) : '');
+        var same = that.node.same(node);
+        if (same) console.debug('[BMA] Skipping fallback node [{0}]: same as current BMA node'.format(node.server));
+        return !same;
+      });
+
+      var aliveNodes = [];
+      return $q.all(_.map(fallbackNodes, function(node) {
+        return that.isAlive(node, timeout)
+          .then(function(alive) {
+            if (alive) {
+              aliveNodes.push(node);
+            }
+            else {
+              console.error('[BMA] Unreacheable (or not compatible) fallback node [{0}]: skipping'.format(node.server));
+            }
+          })
+        }))
+        .then(function() {
+          return aliveNodes;
+        });
+    }
+
     that.api.registerEvent('node', 'start');
     that.api.registerEvent('node', 'stop');
     that.api.registerEvent('node', 'restart');
diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js
index e38aad0dfab5e25287d585dac660c6cc1dcd202f..64b14df498ae2c3206c87a7c0a9bd3ee9e6f2a4b 100644
--- a/www/js/services/network-services.js
+++ b/www/js/services/network-services.js
@@ -12,6 +12,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
     },
     isHttpsMode = $window.location.protocol === 'https:',
     api = new Api(this, "csNetwork"),
+    startPromise,
 
     data = {
       bma: null,
@@ -169,7 +170,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
           // The peer lookup end, we can make a clean final report
           sortPeers(true/*update main buid*/);
 
-          console.debug('[network] Finish: {0} peers found.'.format(data.peers.length));
+          console.debug('[network] {0} peers found.'.format(data.peers.length));
         }
       }, 1000);
 
@@ -286,6 +287,11 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
         })
         .then(function(){
           data.searchingPeersOnNetwork = false;
+          data.loading = false;
+          if (newPeers.length) {
+            flushNewPeersAndSort(newPeers, true/*update main buid*/);
+          }
+          return data.peers;
         })
         .catch(function(err){
           console.error(err);
@@ -755,7 +761,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
 
     start = function(bma, options) {
       options = options || {};
-      return BMA.ready()
+      startPromise = BMA.ready()
         .then(function() {
           close();
 
@@ -775,17 +781,18 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
           }
         })
         .then(function() {
-          console.info('[network] Starting network from [{0}]'.format(bma.server));
+          console.info('[network] Starting from [{0}]'.format(bma.server));
           var now = Date.now();
 
           addListeners();
 
           return loadPeers()
             .then(function(peers){
-              console.debug('[network] Started in '+(Date.now() - now)+'ms');
-              return peers;
+              console.debug('[network] Started in {0}ms, {1} peers found'.format(Date.now() - now, peers.length));
+              return data;
             });
         });
+      return startPromise;
     },
 
     close = function() {
@@ -797,36 +804,47 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
     },
 
     isStarted = function() {
-      return !data.bma;
+      return !!data.bma;
     },
 
-    $q_started = function(callback) {
-      if (!isStarted()) { // start first
-        return start()
+    startIfNeed = function(bma, options) {
+      if (startPromise) return startPromise;
+      if (!isStarted()) {
+        // Start (then stop) if need
+        return start(bma, options)
           .then(function() {
-            return $q(callback);
+            close();
+            return data;
           });
       }
       else {
-        return $q(callback);
+        return $q.resolve(data);
       }
     },
 
-    getMainBlockUid = function() {
-      return $q_started(function(resolve, reject){
-        resolve (data.mainBuid);
-      });
+    getMainBlockUid = function(bma, options) {
+      return startIfNeed(bma, options)
+        .then(function(data) {
+          return data.mainBlock && data.mainBlock.buid;
+        });
     },
 
     // Get peers on the main consensus blocks
-    getTrustedPeers = function() {
-      return $q_started(function(resolve, reject){
-        resolve(data.peers.reduce(function(res, peer){
-          return (peer.hasMainConsensusBlock && peer.uid) ? res.concat(peer) : res;
-        }, []));
-      });
-    }
-    ;
+    getSynchronizedBmaPeers = function(bma, options) {
+      options = options || {};
+      options.filter = options.filter || {};
+      options.filter.bma = angular.isDefined(options.filter.bma) ? options.filter.bma : true;
+      options.filter.ssl = isHttpsMode ? true : undefined;
+      options.filter.online = true;
+      options.filter.expertMode = false;
+
+      return startIfNeed(bma, options)
+        .then(function(data){
+          return _.filter(data.peers, function(peer) {
+            return peer.hasMainConsensusBlock && peer.isBma();
+          });
+        });
+    };
 
   // Register extension points
   api.registerEvent('data', 'changed');
@@ -840,7 +858,7 @@ angular.module('cesium.network.services', ['ngApi', 'cesium.currency.services',
     hasPeers: hasPeers,
     getPeers: getPeers,
     sort: sort,
-    getTrustedPeers: getTrustedPeers,
+    getSynchronizedBmaPeers: getSynchronizedBmaPeers,
     getKnownBlocks: getKnownBlocks,
     getMainBlockUid: getMainBlockUid,
     loadPeers: loadPeers,