diff --git a/plugins/metrics/dashboard.html b/plugins/metrics/dashboard.html
new file mode 100644
index 0000000000000000000000000000000000000000..bea93acd4b3c4296da014b77e6e19029ebe0bf41
--- /dev/null
+++ b/plugins/metrics/dashboard.html
@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
+    <script src="https://code.highcharts.com/stock/highstock.js"></script>
+    <script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
+    <script src="https://code.highcharts.com/stock/modules/export-data.js"></script>
+    <div id="container" style="height: 400px; min-width: 310px"></div>
+</head>
+
+<body>
+    <script>
+        Highcharts.createElement('link', {
+            href: 'https://fonts.googleapis.com/css?family=Unica+One',
+            rel: 'stylesheet',
+            type: 'text/css'
+        }, null, document.getElementsByTagName('head')[0]);
+
+        Highcharts.theme = {
+            colors: ['#2b908f', '#90ee7e', '#f45b5b', '#7798BF', '#aaeeee', '#ff0066',
+                '#eeaaee', '#55BF3B', '#DF5353', '#7798BF', '#aaeeee'],
+            chart: {
+                backgroundColor: {
+                    linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 },
+                    stops: [
+                        [0, '#2a2a2b'],
+                        [1, '#3e3e40']
+                    ]
+                },
+                style: {
+                    fontFamily: '\'Unica One\', sans-serif'
+                },
+                plotBorderColor: '#606063'
+            },
+            title: {
+                style: {
+                    color: '#E0E0E3',
+                    textTransform: 'uppercase',
+                    fontSize: '20px'
+                }
+            },
+            subtitle: {
+                style: {
+                    color: '#E0E0E3',
+                    textTransform: 'uppercase'
+                }
+            },
+            xAxis: {
+                gridLineColor: '#707073',
+                labels: {
+                    style: {
+                        color: '#E0E0E3'
+                    }
+                },
+                lineColor: '#707073',
+                minorGridLineColor: '#505053',
+                tickColor: '#707073',
+                title: {
+                    style: {
+                        color: '#A0A0A3'
+
+                    }
+                }
+            },
+            yAxis: {
+                gridLineColor: '#707073',
+                labels: {
+                    style: {
+                        color: '#E0E0E3'
+                    }
+                },
+                lineColor: '#707073',
+                minorGridLineColor: '#505053',
+                tickColor: '#707073',
+                tickWidth: 1,
+                title: {
+                    style: {
+                        color: '#A0A0A3'
+                    }
+                }
+            },
+            tooltip: {
+                backgroundColor: 'rgba(0, 0, 0, 0.85)',
+                style: {
+                    color: '#F0F0F0'
+                }
+            },
+            plotOptions: {
+                series: {
+                    dataLabels: {
+                        color: '#B0B0B3'
+                    },
+                    marker: {
+                        lineColor: '#333'
+                    }
+                },
+                boxplot: {
+                    fillColor: '#505053'
+                },
+                candlestick: {
+                    lineColor: 'white'
+                },
+                errorbar: {
+                    color: 'white'
+                }
+            },
+            legend: {
+                itemStyle: {
+                    color: '#E0E0E3'
+                },
+                itemHoverStyle: {
+                    color: '#FFF'
+                },
+                itemHiddenStyle: {
+                    color: '#606063'
+                }
+            },
+            credits: {
+                style: {
+                    color: '#666'
+                }
+            },
+            labels: {
+                style: {
+                    color: '#707073'
+                }
+            },
+
+            drilldown: {
+                activeAxisLabelStyle: {
+                    color: '#F0F0F3'
+                },
+                activeDataLabelStyle: {
+                    color: '#F0F0F3'
+                }
+            },
+
+            navigation: {
+                buttonOptions: {
+                    symbolStroke: '#DDDDDD',
+                    theme: {
+                        fill: '#505053'
+                    }
+                }
+            },
+
+            // scroll charts
+            rangeSelector: {
+                buttonTheme: {
+                    fill: '#505053',
+                    stroke: '#000000',
+                    style: {
+                        color: '#CCC'
+                    },
+                    states: {
+                        hover: {
+                            fill: '#707073',
+                            stroke: '#000000',
+                            style: {
+                                color: 'white'
+                            }
+                        },
+                        select: {
+                            fill: '#000003',
+                            stroke: '#000000',
+                            style: {
+                                color: 'white'
+                            }
+                        }
+                    }
+                },
+                inputBoxBorderColor: '#505053',
+                inputStyle: {
+                    backgroundColor: '#333',
+                    color: 'silver'
+                },
+                labelStyle: {
+                    color: 'silver'
+                }
+            },
+
+            navigator: {
+                handles: {
+                    backgroundColor: '#666',
+                    borderColor: '#AAA'
+                },
+                outlineColor: '#CCC',
+                maskFill: 'rgba(255,255,255,0.1)',
+                series: {
+                    color: '#7798BF',
+                    lineColor: '#A6C7ED'
+                },
+                xAxis: {
+                    gridLineColor: '#505053'
+                }
+            },
+
+            scrollbar: {
+                barBackgroundColor: '#808083',
+                barBorderColor: '#808083',
+                buttonArrowColor: '#CCC',
+                buttonBackgroundColor: '#606063',
+                buttonBorderColor: '#606063',
+                rifleColor: '#FFF',
+                trackBackgroundColor: '#404043',
+                trackBorderColor: '#404043'
+            },
+
+            // special colors for some of the
+            legendBackgroundColor: 'rgba(0, 0, 0, 0.5)',
+            background2: '#505053',
+            dataLabelsColor: '#B0B0B3',
+            textColor: '#C0C0C0',
+            contrastTextColor: '#F0F0F3',
+            maskColor: 'rgba(255,255,255,0.3)'
+        };
+
+        // Apply the theme
+        Highcharts.setOptions(Highcharts.theme);
+
+        // Start Here
+        var time = Date.now() - 3000;
+        var start_draw = time + 5000;
+        const update_rate = 5;
+        var counter = 0;
+        data = [[time - 5000, 0]];
+        var tzoffset = new Date().getTimezoneOffset();
+        var chart = Highcharts.stockChart('container', {
+            rangeSelector: {
+                selected: 1
+            },
+
+            title: {
+                text: 'Transaction per Second'
+            },
+
+            time: {
+                timezoneOffset: tzoffset
+            },
+
+            rangeSelector: {
+                buttons: [
+                    {
+                        type: 'minute',
+                        count: 5,
+                        text: '5m'
+                    }, {
+                        type: 'minute',
+                        count: 15,
+                        text: '15m'
+                    }, {
+                        type: 'minute',
+                        count: 30,
+                        text: '30m'
+                    }, {
+                        type: 'hour',
+                        count: 60,
+                        text: '1h'
+                    }],
+                inputEnabled: false
+            },
+
+            series: [{
+                name: 'Transaction per Second',
+                data: data,
+                type: 'areaspline',
+                threshold: null,
+                tooltip: {
+                    valueDecimals: 0
+                },
+                fillColor: {
+                    linearGradient: {
+                        x1: 0,
+                        y1: 0,
+                        x2: 0,
+                        y2: 1
+                    },
+                    stops: [
+                        [0, Highcharts.getOptions().colors[0]],
+                        [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')]
+                    ]
+                }
+            }]
+        });
+        const conn = new WebSocket("ws://{{.Host}}/ws");
+        conn.binaryType = 'arraybuffer';
+        conn.onopen = evt => {
+            console.log("WebSocket is open now.");
+            const dataStr = '{{.Data}}'
+            const data = JSON.parse(dataStr.replace(/ /g, ','));
+            time = Date.now() - 1000 * (data.length + 1);
+            for (let i = 0; i < data.length; i++) {
+                chart.series[0].addPoint([time += 1000, parseInt(data[i], 10)], true);
+            }
+            console.log(data);
+            console.log("WebSocket done.");
+        }
+        conn.onclose = () => {
+            // console.log('Connection closed');
+        }
+        conn.onmessage = evt => {
+            console.log('metric updated');
+            const data = evt.data;
+            const dv = new DataView(data);
+            // var value = dv.getUint32(4, true) << 32 | dv.getUint32(0, true);
+            const value = dv.getUint32(0, true);
+            chart.series[0].addPoint([time += 1000, value], true); //((counter += 1) % update_rate == 4));
+            console.log(value);
+            console.log(dv);
+        }
+    </script>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/plugins/metrics/plugin.go b/plugins/metrics/plugin.go
index 837a7bfe8ca3514c2481f936b963ede50aa966bf..ab375acebbe997147a74be7b6ad6a1516eb41239 100644
--- a/plugins/metrics/plugin.go
+++ b/plugins/metrics/plugin.go
@@ -1,8 +1,12 @@
 package metrics
 
 import (
+	"encoding/binary"
+	"log"
+	"net/http"
 	"time"
 
+	"github.com/gorilla/websocket"
 	"github.com/iotaledger/goshimmer/packages/daemon"
 	"github.com/iotaledger/goshimmer/packages/events"
 	"github.com/iotaledger/goshimmer/packages/model/meta_transaction"
@@ -15,13 +19,39 @@ import (
 func configure(plugin *node.Plugin) {
 	// increase received TPS counter whenever we receive a new transaction
 	gossip.Events.ReceiveTransaction.Attach(events.NewClosure(func(_ *meta_transaction.MetaTransaction) { increaseReceivedTPSCounter() }))
+
+	// send the sampledTPS to client via websocket, use uint32 to save mem
+	Events.ReceivedTPSUpdated.Attach(events.NewClosure(func(sampledTPS uint64) {
+		for client := range Clients {
+			p := make([]byte, 4)
+			binary.LittleEndian.PutUint32(p, uint32(sampledTPS))
+			if err := client.WriteMessage(websocket.BinaryMessage, p); err != nil {
+				return
+			}
+			TPSQ = append(TPSQ, uint32(sampledTPS))
+			if len(TPSQ) > MAX_Q_SIZE {
+				TPSQ = TPSQ[1:]
+			}
+		}
+	}))
 }
 
 // create run handler (get's called when the PLUGIN is "executed" by the node)
 func run(plugin *node.Plugin) {
 	// create a background worker that "measures" the TPS value every second
 	daemon.BackgroundWorker("Metrics TPS Updater", func() { timeutil.Ticker(measureReceivedTPS, 1*time.Second) })
+	daemon.BackgroundWorker("Dashboard Updater", func() {
+		http.HandleFunc("/dashboard", ServeHome)
+		http.HandleFunc("/ws", ServeWs)
+		if err := http.ListenAndServe(":8081", nil); err != nil {
+			log.Fatal(err)
+		}
+	})
 }
 
 // export plugin
 var PLUGIN = node.NewPlugin("Metrics", configure, run)
+
+// TPS queue
+var TPSQ []uint32
+var MAX_Q_SIZE int = 3600
diff --git a/plugins/metrics/server.go b/plugins/metrics/server.go
new file mode 100644
index 0000000000000000000000000000000000000000..1cccf6d24de4dc974f723e6c62ee25875510ece6
--- /dev/null
+++ b/plugins/metrics/server.go
@@ -0,0 +1,56 @@
+package metrics
+
+import (
+	"html/template"
+	"log"
+	"net/http"
+	"path/filepath"
+	"runtime"
+
+	"github.com/gorilla/websocket"
+)
+
+var (
+	_, filename, _, _ = runtime.Caller(0)
+	Clients           = make(map[*websocket.Conn]bool)
+	templPath         = filepath.Join(filepath.Dir(filename), "./dashboard.html")
+	homeTempl, _      = template.ParseFiles(templPath)
+	upgrader          = websocket.Upgrader{
+		ReadBufferSize:  1024,
+		WriteBufferSize: 1024,
+	}
+)
+
+// ServeWs websocket
+func ServeWs(w http.ResponseWriter, r *http.Request) {
+	ws, err := upgrader.Upgrade(w, r, nil)
+	if err != nil {
+		if _, ok := err.(websocket.HandshakeError); !ok {
+			log.Println(err)
+		}
+		return
+	}
+	Clients = make(map[*websocket.Conn]bool)
+	Clients[ws] = true
+}
+
+// ServeHome registration
+func ServeHome(w http.ResponseWriter, r *http.Request) {
+	if r.URL.Path != "/dashboard" {
+		http.Error(w, "Not found", http.StatusNotFound)
+		return
+	}
+	if r.Method != "GET" {
+		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+		return
+	}
+
+	var v = struct {
+		Host string
+		Data []uint32
+	}{
+		r.Host,
+		TPSQ,
+	}
+	homeTempl.Execute(w, &v)
+}