diff --git a/www/index.html b/www/index.html
index 6d86e543ee8a9064cee048804a5523edc9d0cd79..f8d64a11f70b03b3d9b65e91a4168dbabb8efe57 100644
--- a/www/index.html
+++ b/www/index.html
@@ -200,6 +200,7 @@
 <script src="dist/dist_js/plugins/graph/js/controllers/currency-controllers.js"></script>
 <script src="dist/dist_js/plugins/graph/js/controllers/account-controllers.js"></script>
 <script src="dist/dist_js/plugins/graph/js/controllers/docstats-controllers.js"></script>
+<script src="dist/dist_js/plugins/graph/js/controllers/synchro-controllers.js"></script>
 <!--endRemoveIf(ubuntu)-->
 
 <!-- Map plugin -->
diff --git a/www/plugins/graph/i18n/locale-fr-FR.json b/www/plugins/graph/i18n/locale-fr-FR.json
index af9f181845731507e68ab8963055aaacbd11bcbc..1501f1268fe804ad67849106efdedbe976e37356 100644
--- a/www/plugins/graph/i18n/locale-fr-FR.json
+++ b/www/plugins/graph/i18n/locale-fr-FR.json
@@ -89,6 +89,14 @@
         "TITLE": "Autres documents",
         "HISTORY_DELETE": "Suppressions de documents",
       }
+    },
+    "SYNCHRO": {
+      "EXECUTION": {
+        "TITLE": "Synchronisation",
+        "INSERTS": "Insertions",
+        "UPDATES": "Mises à jour",
+        "DELETES": "Suppressions"
+      }
     }
   }
 }
diff --git a/www/plugins/graph/js/controllers/common-controllers.js b/www/plugins/graph/js/controllers/common-controllers.js
index 95fb03db848488a8f267b226eca5d8fc4d81aacf..1f79881825fa04ffe562d5921a9043b6031cfbc7 100644
--- a/www/plugins/graph/js/controllers/common-controllers.js
+++ b/www/plugins/graph/js/controllers/common-controllers.js
@@ -72,6 +72,7 @@ function GpCurrencyAbstractController($scope, $filter, $ionicPopover, $ionicHist
               console.warn('[graph] currency.firstBlockTime not loaded ! Should have been loaded by currrency service!');
             }
             $scope.formData.currencyAge = _truncDate(esHttp.date.now()) - $scope.formData.firstBlockTime;
+
             return $scope.enter(e, state);
           });
       }
diff --git a/www/plugins/graph/js/controllers/docstats-controllers.js b/www/plugins/graph/js/controllers/docstats-controllers.js
index f864345ab8af23f951429f631998311c97362212..d868d1101fc0bb5fd8c30f870c1bd1ecdabe0170 100644
--- a/www/plugins/graph/js/controllers/docstats-controllers.js
+++ b/www/plugins/graph/js/controllers/docstats-controllers.js
@@ -9,7 +9,8 @@ angular.module('cesium.graph.docstats.controllers', ['chart.js', 'cesium.graph.s
         url: "/data/stats?stepUnit&t&hide&scale",
         views: {
           'menuContent': {
-            templateUrl: "plugins/graph/templates/docstats/view_doc_stats_lg.html"
+            templateUrl: "plugins/graph/templates/docstats/view_stats.html",
+            controller: 'GpDocStatsCtrl'
           }
         }
       });
@@ -43,7 +44,7 @@ function GpDocStatsController($scope, $controller, $q, $translate, gpColor, gpDa
           key: 'user_profile',
           label: 'GRAPH.DOC_STATS.USER.USER_PROFILE',
           color: gpColor.rgba.royal(1),
-          pointHoverBackgroundColor: gpColor.rgba.gray(1)
+          pointHoverBackgroundColor: gpColor.rgba.royal(1)
         },
         {
           key: 'user_settings',
@@ -161,7 +162,6 @@ function GpDocStatsController($scope, $controller, $q, $translate, gpColor, gpDa
 
   $scope.load = function(updateTimePct) {
 
-
     return $q.all([
       // Get i18n keys (chart title, series labels, date patterns)
       $translate($scope.charts.reduce(function(res, chart) {
diff --git a/www/plugins/graph/js/controllers/synchro-controllers.js b/www/plugins/graph/js/controllers/synchro-controllers.js
new file mode 100644
index 0000000000000000000000000000000000000000..580ce9d93ab67a5fd52c4f03f35e5c7e8cc5fd09
--- /dev/null
+++ b/www/plugins/graph/js/controllers/synchro-controllers.js
@@ -0,0 +1,187 @@
+
+angular.module('cesium.graph.synchro.controllers', ['chart.js', 'cesium.graph.services', 'cesium.graph.common.controllers'])
+
+  .config(function($stateProvider, PluginServiceProvider, csConfig) {
+    'ngInject';
+
+    $stateProvider
+      .state('app.doc_synchro_lg', {
+        url: "/data/synchro?stepUnit&t&hide&scale",
+        views: {
+          'menuContent': {
+            templateUrl: "plugins/graph/templates/synchro/view_stats.html",
+            controller: "GpSynchroCtrl"
+          }
+        }
+      });
+
+    var enable = csConfig.plugins && csConfig.plugins.es;
+    if (enable) {
+      // TODO: add buttons to link with doc stats
+    }
+  })
+
+
+  .controller('GpSynchroCtrl', GpSynchroController)
+;
+
+function GpSynchroController($scope, $controller, $q, $translate, gpColor, gpData, $filter) {
+  'ngInject';
+
+  // Initialize the super class and extend it.
+  angular.extend(this, $controller('GpCurrencyAbstractCtrl', {$scope: $scope}));
+
+  $scope.hiddenDatasets = [];
+
+  $scope.charts = [
+
+    // User count
+    {
+      id: 'user',
+      title: 'GRAPH.SYNCHRO.EXECUTION.TITLE',
+      series: [
+        {
+          key: 'inserts',
+          label: 'GRAPH.SYNCHRO.EXECUTION.INSERTS',
+          color: gpColor.rgba.royal(1),
+          pointHoverBackgroundColor: gpColor.rgba.royal(1)
+        },
+        {
+          key: 'updates',
+          label: 'GRAPH.SYNCHRO.EXECUTION.UPDATES',
+          color: gpColor.rgba.calm(1),
+          pointHoverBackgroundColor: gpColor.rgba.calm(1)
+        },
+        {
+          key: 'deletes',
+          label: 'GRAPH.SYNCHRO.EXECUTION.DELETES',
+          color: gpColor.rgba.assertive(0.5),
+          pointHoverBackgroundColor: gpColor.rgba.assertive(1)
+        }
+      ]
+    }
+  ];
+
+  var formatInteger = $filter('formatInteger');
+
+  $scope.defaultChartOptions = {
+    responsive: true,
+    maintainAspectRatio: $scope.maintainAspectRatio,
+    title: {
+      display: true
+    },
+    legend: {
+      display: true,
+      onClick: $scope.onLegendClick
+    },
+    scales: {
+      yAxes: [
+        {
+          stacked: true,
+          id: 'y-axis'
+        }
+      ]
+    },
+    tooltips: {
+      enabled: true,
+      mode: 'index',
+      callbacks: {
+        label: function(tooltipItems, data) {
+          return data.datasets[tooltipItems.datasetIndex].label +
+            ': ' + formatInteger(tooltipItems.yLabel);
+        }
+      }
+    }
+  };
+
+  $scope.init = function(e, state) {
+    if (state && state.stateParams) {
+      // Manage URL parameters
+    }
+  };
+
+  $scope.load = function(updateTimePct) {
+
+    return $q.all([
+      // Get i18n keys (chart title, series labels, date patterns)
+      $translate($scope.charts.reduce(function(res, chart) {
+        return res.concat(chart.series.reduce(function(res, serie) {
+          return res.concat(serie.label);
+        }, [chart.title]));
+      }, [
+        'COMMON.DATE_PATTERN',
+        'COMMON.DATE_SHORT_PATTERN',
+        'COMMON.DATE_MONTH_YEAR_PATTERN'
+      ])),
+
+      // get Data
+      gpData.synchro.execution.get($scope.formData)
+    ])
+    .then(function(result) {
+      var translations = result[0];
+      var datePatterns = {
+        hour: translations['COMMON.DATE_PATTERN'],
+        day: translations['COMMON.DATE_SHORT_PATTERN'],
+        month: translations['COMMON.DATE_MONTH_YEAR_PATTERN']
+      };
+
+      result = result[1];
+      console.log("TODO", result);
+      if (!result || !result.times) return; // no data
+      $scope.times = result.times;
+
+      // Labels
+      var labelPattern = datePatterns[$scope.formData.rangeDuration];
+      $scope.labels = result.times.reduce(function(res, time) {
+        return res.concat(moment.unix(time).local().format(labelPattern));
+      }, []);
+
+      // Update range options with received values
+      $scope.updateRange(result.times[0], result.times[result.times.length-1], updateTimePct);
+
+      $scope.setScale($scope.scale);
+
+      // For each chart
+      _.forEach($scope.charts, function(chart){
+
+        // Data
+        chart.data = [];
+        _.forEach(chart.series, function(serie){
+          chart.data.push(result[serie.key]||[]);
+        });
+
+        // Options (with title)
+        chart.options = angular.copy($scope.defaultChartOptions);
+        chart.options.title.text = translations[chart.title];
+
+        // Series datasets
+        chart.datasetOverride = chart.series.reduce(function(res, serie) {
+          return res.concat({
+            yAxisID: 'y-axis',
+            type: 'bar',
+            label: translations[serie.label],
+            fill: true,
+            borderColor: serie.color,
+            borderWidth: 2,
+            backgroundColor: serie.color,
+            pointBackgroundColor: serie.color,
+            pointBorderColor: gpColor.rgba.white(),
+            pointHoverBackgroundColor: serie.pointHoverBackgroundColor||serie.color,
+            pointHoverBorderColor: gpColor.rgba.translucent(),
+            pointRadius: 3
+          });
+        }, []);
+      });
+    });
+
+  };
+
+  $scope.onChartClick = function(data, e, item) {
+    if (!item) return;
+    console.log('Click on item index='+ item._index);
+    var from = $scope.times[item._index];
+    var to = moment.unix(from).utc().add(1, $scope.formData.rangeDuration).unix();
+  };
+
+
+}
diff --git a/www/plugins/graph/js/plugin.js b/www/plugins/graph/js/plugin.js
index d91d14b069a5bc908d375c902f547dd35073ed27..afb599035bba0dfcda52812c39223e1db11cd0e0 100644
--- a/www/plugins/graph/js/plugin.js
+++ b/www/plugins/graph/js/plugin.js
@@ -9,5 +9,6 @@ angular.module('cesium.graph.plugin', [
     'cesium.graph.currency.controllers',
     'cesium.graph.account.controllers',
     'cesium.graph.docstats.controllers',
+    'cesium.graph.synchro.controllers'
   ])
 ;
diff --git a/www/plugins/graph/js/services/data-services.js b/www/plugins/graph/js/services/data-services.js
index c7f92796f298e13e9a77ec2843ab64ac1c457587..b9bfdfdfb178b852367603ce58d3da5a7b70342f 100644
--- a/www/plugins/graph/js/services/data-services.js
+++ b/www/plugins/graph/js/services/data-services.js
@@ -10,6 +10,9 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.
         wot: {},
         blockchain: {},
         docstat: {},
+        synchro: {
+          execution: {}
+        },
         raw: {
           block: {
             search: esHttp.post('/:currency/block/_search')
@@ -25,6 +28,9 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.
           },
           docstat: {
             search: esHttp.post('/docstat/record/_search')
+          },
+          synchro: {
+            search: esHttp.post('/:currency/synchro/_search')
           }
         },
         regex: {
@@ -775,6 +781,114 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.
         });
     };
 
+
+    /**
+     * Graph: "statictics on ES documents"
+     * @param currency
+     * @returns {*}
+     */
+    exports.synchro.execution.get = function(options) {
+
+      options = _initRangeOptions(options);
+
+      var jobs = [];
+
+      var from = moment.unix(options.startTime).utc().startOf(options.rangeDuration);
+      var to = moment.unix(options.endTime).utc().startOf(options.rangeDuration);
+      var ranges = [];
+      while(from.isBefore(to)) {
+
+        ranges.push({
+          from: from.unix(),
+          to: from.add(1, options.rangeDuration).unix()
+        });
+
+        // Flush if max range count, or just before loop condition end (fix #483)
+        var flush = (ranges.length === options.maxRangeSize) || !from.isBefore(to);
+        if (flush) {
+          var request = {
+            size: 0,
+            aggs: {
+              range: {
+                range: {
+                  field: "time",
+                  ranges: ranges
+                },
+                aggs: {
+                  result: {
+                    nested: {
+                      path: "result"
+                    },
+                    aggs: {
+                      inserts : {
+                        sum: {
+                          field : "result.inserts"
+                        }
+                      },
+                      updates : {
+                        sum: {
+                          field : "result.updates"
+                        }
+                      },
+                      deletes : {
+                        sum: {
+                          field : "result.deletes"
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+
+          };
+
+          // prepare next loop
+          ranges = [];
+
+          if (jobs.length == 10) {
+            console.error('Too many parallel jobs!');
+            from = moment.unix(options.endTime).utc(); // stop while
+          }
+          else {
+            jobs.push(
+              exports.raw.synchro.search(request, {currency: options.currency})
+                .then(function (res) {
+                  var aggs = res.aggregations;
+
+                  return (aggs.range && aggs.range.buckets || []).reduce(function (res, agg) {
+                    return res.concat({
+                      from: agg.from,
+                      to: agg.to,
+                      inserts: agg.result.inserts.value,
+                      updates: agg.result.inserts.value,
+                      deletes: agg.result.deletes.value
+                    });
+                  }, []);
+                })
+            );
+          }
+        }
+      } // loop
+
+      return $q.all(jobs)
+        .then(function(res) {
+          res = res.reduce(function(res, hits){
+            if (!hits || !hits.length) return res;
+            return res.concat(hits);
+          }, []);
+
+          res = _.sortBy(res, 'from');
+
+          return {
+            times: _.pluck(res, 'from'),
+            inserts: _.pluck(res, 'inserts'),
+            updates: _.pluck(res, 'updates'),
+            deletes: _.pluck(res, 'deletes')
+          };
+        });
+    };
+
     return exports;
   })
 
diff --git a/www/plugins/graph/templates/docstats/graph_doc_stats.html b/www/plugins/graph/templates/docstats/graph.html
similarity index 100%
rename from www/plugins/graph/templates/docstats/graph_doc_stats.html
rename to www/plugins/graph/templates/docstats/graph.html
diff --git a/www/plugins/graph/templates/docstats/view_doc_stats_lg.html b/www/plugins/graph/templates/docstats/view_doc_stats_lg.html
deleted file mode 100644
index e18218d7a7f9c19a2451b030d9df177f1c4fcf70..0000000000000000000000000000000000000000
--- a/www/plugins/graph/templates/docstats/view_doc_stats_lg.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<ion-view left-buttons="leftButtons"
-          cache-view="false">
-  <ion-nav-title>
-    {{'GRAPH.DOC_STATS.TITLE' | translate}}
-  </ion-nav-title>
-
-  <ion-content scroll="true" class="padding" >
-
-
-
-    <div class="list" >
-
-      <!-- Doc stat -->
-      <ng-controller ng-controller="GpDocStatsCtrl" >
-
-        <div class="center padding" ng-if="loading">
-          <ion-spinner icon="android"></ion-spinner>
-        </div>
-
-        <div class="item no-padding-xs" ng-if="!loading"
-             ng-repeat="chart in charts"
-             ng-include="'plugins/graph/templates/docstats/graph_doc_stats.html'"
-             ng-init="setSize(250, 1000)">
-        </div>
-      </ng-controller>
-
-
-
-    </div>
-
-  </ion-content>
-
-</ion-view>
diff --git a/www/plugins/graph/templates/docstats/view_stats.html b/www/plugins/graph/templates/docstats/view_stats.html
new file mode 100644
index 0000000000000000000000000000000000000000..dfea0e947cae1f356e5ca05b660a1c8e5fd112a3
--- /dev/null
+++ b/www/plugins/graph/templates/docstats/view_stats.html
@@ -0,0 +1,26 @@
+<ion-view left-buttons="leftButtons"
+          cache-view="false">
+  <ion-nav-title>
+    {{'GRAPH.DOC_STATS.TITLE' | translate}}
+  </ion-nav-title>
+
+  <ion-content scroll="true" class="padding" >
+
+    <div class="list" >
+
+      <!-- Doc stat -->
+      <div class="center padding" ng-if="loading">
+        <ion-spinner icon="android"></ion-spinner>
+      </div>
+
+      <div class="item no-padding-xs" ng-if="!loading"
+           ng-repeat="chart in charts"
+           ng-include="'plugins/graph/templates/docstats/graph.html'"
+           ng-init="setSize(250, 1000)">
+      </div>
+
+    </div>
+
+  </ion-content>
+
+</ion-view>
diff --git a/www/plugins/graph/templates/synchro/graph.html b/www/plugins/graph/templates/synchro/graph.html
new file mode 100644
index 0000000000000000000000000000000000000000..19ac3b723b553020daf60208a1d88f7541e063f9
--- /dev/null
+++ b/www/plugins/graph/templates/synchro/graph.html
@@ -0,0 +1,22 @@
+
+  <!-- graphs button bar -->
+  <div class="button-bar-inline "
+       style="top: 33px; margin-top:-33px; position: relative;">
+    <button
+      class="button button-stable button-clear no-padding-xs pull-right"
+      ng-click="showActionsPopover($event)">
+      <i class="icon ion-navicon-round"></i>
+    </button>
+  </div>
+
+  <canvas id="synchro-chart-{{chart.id}}"
+          class="chart-bar"
+          height="{{height}}"
+          width="{{width}}"
+          chart-data="chart.data"
+          chart-labels="labels"
+          chart-dataset-override="chart.datasetOverride"
+          chart-options="chart.options">
+  </canvas>
+
+  <ng-include src="'plugins/graph/templates/common/graph_range_bar.html'"></ng-include>
diff --git a/www/plugins/graph/templates/synchro/view_stats.html b/www/plugins/graph/templates/synchro/view_stats.html
new file mode 100644
index 0000000000000000000000000000000000000000..ec7f0ad311175c9e8c6cfae7f57edf16d4f77fbc
--- /dev/null
+++ b/www/plugins/graph/templates/synchro/view_stats.html
@@ -0,0 +1,25 @@
+<ion-view left-buttons="leftButtons"
+          cache-view="false">
+  <ion-nav-title>
+    {{'GRAPH.DOC_STATS.TITLE' | translate}}
+  </ion-nav-title>
+
+  <ion-content scroll="true" class="padding" >
+
+    <div class="list" >
+
+      <div class="center padding" ng-if="loading">
+        <ion-spinner icon="android"></ion-spinner>
+      </div>
+
+      <div class="item no-padding-xs" ng-if="!loading"
+           ng-repeat="chart in charts"
+           ng-include="'plugins/graph/templates/synchro/graph.html'"
+           ng-init="setSize(250, 1000)">
+      </div>
+
+    </div>
+
+  </ion-content>
+
+</ion-view>